diff --git a/.github/gh_matrix_builder.py b/.github/gh_matrix_builder.py index d59ccc66390..b1f296b5a72 100755 --- a/.github/gh_matrix_builder.py +++ b/.github/gh_matrix_builder.py @@ -79,9 +79,6 @@ def build_debug_config(overrides): "tsdb_build_args": "-DWARNINGS_AS_ERRORS=ON -DREQUIRE_ALL_TESTS=ON", } ) - # We use .get() here to be able to handle also configurations without PG versions - if not pull_request or overrides.get("pg") == PG15_LATEST: - base_config["tsdb_build_args"] += " -DENABLE_MULTINODE_TESTS=ON" base_config.update(overrides) return base_config @@ -100,8 +97,6 @@ def build_release_config(overrides): "coverage": False, } ) - if not pull_request: - release_config["tsdb_build_args"] += " -DENABLE_MULTINODE_TESTS=ON" base_config.update(release_config) base_config.update(overrides) return base_config @@ -157,8 +152,6 @@ def macos_config(overrides): "tsdb_build_args": "-DASSERTIONS=ON -DREQUIRE_ALL_TESTS=ON -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl", } ) - if not pull_request: - base_config["tsdb_build_args"] += " -DENABLE_MULTINODE_TESTS=ON" base_config.update(overrides) return base_config @@ -167,7 +160,6 @@ def macos_config(overrides): ignored_tests = {} # common ignored tests for all non-scheduled pg15 tests (e.g. PRs) -# dist_move_chunk, dist_param, dist_insert, and remote_txn ignored due to flakiness if pull_request: ignored_tests = { "telemetry", @@ -225,10 +217,9 @@ def macos_config(overrides): "pg_extra_args": "--enable-debug --enable-cassert --without-llvm", "skipped_tests": {"001_extension"}, "ignored_tests": { - "dist_gapfill_pushdown-13", "transparent_decompress_chunk-13", }, - "tsdb_build_args": "-DWARNINGS_AS_ERRORS=ON -DASSERTIONS=ON -DPG_ISOLATION_REGRESS=OFF -DENABLE_MULTINODE_TESTS=ON", + "tsdb_build_args": "-DWARNINGS_AS_ERRORS=ON -DASSERTIONS=ON -DPG_ISOLATION_REGRESS=OFF", } m["include"].append(build_debug_config(pg13_debug_earliest)) @@ -239,7 +230,7 @@ def macos_config(overrides): "pg": PG14_EARLIEST, # The early releases don't build with llvm 14. "pg_extra_args": "--enable-debug --enable-cassert --without-llvm", - "ignored_tests": {"dist_gapfill_pushdown-14 memoize"}, + "ignored_tests": {"memoize"}, } ) ) @@ -287,7 +278,7 @@ def macos_config(overrides): m["include"].append( build_debug_config( { - "ignored_tests": {"dist_gapfill_pushdown-14 memoize"}, + "ignored_tests": {"memoize"}, "pg": 14, "snapshot": "snapshot", } diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index 92b3fa89296..fe81a9dfc7b 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -41,9 +41,7 @@ jobs: CC: clang-14 CXX: clang++-14 DEBIAN_FRONTEND: noninteractive - IGNORES: "append-* debug_notice transparent_decompression-* - transparent_decompress_chunk-* pg_dump - dist_move_chunk dist_param dist_insert remote_txn telemetry" + IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry" SKIPS: chunk_adaptive histogram_test-* strategy: fail-fast: false diff --git a/.github/workflows/sanitizer-build-and-test.yaml b/.github/workflows/sanitizer-build-and-test.yaml index a9c2f6d36c4..a694029894e 100644 --- a/.github/workflows/sanitizer-build-and-test.yaml +++ b/.github/workflows/sanitizer-build-and-test.yaml @@ -143,7 +143,7 @@ jobs: - name: Build TimescaleDB run: | - ./bootstrap -DCMAKE_BUILD_TYPE=Debug -DPG_SOURCE_DIR=~/$PG_SRC_DIR -DENABLE_MULTINODE_TESTS=ON \ + ./bootstrap -DCMAKE_BUILD_TYPE=Debug -DPG_SOURCE_DIR=~/$PG_SRC_DIR \ -DPG_PATH=~/$PG_INSTALL_DIR -DCODECOVERAGE=OFF -DREQUIRE_ALL_TESTS=ON -DTEST_GROUP_SIZE=5 make -j$(nproc) -C build make -C build install diff --git a/.github/workflows/windows-build-and-test.yaml b/.github/workflows/windows-build-and-test.yaml index 7d263af853b..d01531eab4a 100644 --- a/.github/workflows/windows-build-and-test.yaml +++ b/.github/workflows/windows-build-and-test.yaml @@ -53,19 +53,18 @@ jobs: os: [ windows-2022 ] build_type: ${{ fromJson(needs.config.outputs.build_type) }} ignores: ["chunk_adaptive metadata telemetry"] - tsl_ignores: ["compression_algos remote_connection dist_move_chunk dist_param dist_insert dist_backup dist_cagg"] - tsl_skips: ["bgw_db_scheduler bgw_db_scheduler_fixed cagg_ddl_dist_ht - data_fetcher dist_compression dist_remote_error remote_txn"] + tsl_ignores: ["compression_algos"] + tsl_skips: ["bgw_db_scheduler bgw_db_scheduler_fixed"] pg_config: ["-cfsync=off -cstatement_timeout=60s"] include: - pg: 13 - tsl_skips_version: dist_grant-13 dist_partial_agg-13 telemetry_stats-13 + tsl_skips_version: telemetry_stats-13 - pg: 14 - tsl_skips_version: dist_partial_agg-14 dist_grant-14 telemetry_stats-14 + tsl_skips_version: telemetry_stats-14 - pg: 15 - tsl_skips_version: dist_partial_agg-15 dist_grant-15 telemetry_stats-15 + tsl_skips_version: telemetry_stats-15 - pg: 16 - tsl_skips_version: dist_partial_agg-16 dist_grant-16 telemetry_stats-16 + tsl_skips_version: telemetry_stats-16 env: # PostgreSQL configuration PGPORT: 55432 diff --git a/CMakeLists.txt b/CMakeLists.txt index 916a8a4f8fc..e88e639df79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,6 @@ option( "Enable OPTIMIZER_DEBUG when building. Requires Postgres server to be built with OPTIMIZER_DEBUG." OFF) option(ENABLE_DEBUG_UTILS "Enable debug utilities for the extension." ON) -option(ENABLE_MULTINODE_TESTS "Enable multinode-specific tests" OFF) # Option to enable assertions. Note that if we include headers from a PostgreSQL # build that has assertions enabled, we might inherit that setting without diff --git a/tsl/test/expected/cagg_bgw_dist_ht.out b/tsl/test/expected/cagg_bgw_dist_ht.out deleted file mode 100644 index 5b85e7de721..00000000000 --- a/tsl/test/expected/cagg_bgw_dist_ht.out +++ /dev/null @@ -1,744 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_cagg_bgw_dist_ht_1 | db_cagg_bgw_dist_ht_1 | t | t | t - db_cagg_bgw_dist_ht_2 | db_cagg_bgw_dist_ht_2 | t | t | t - db_cagg_bgw_dist_ht_3 | db_cagg_bgw_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\set IS_DISTRIBUTED TRUE -\ir include/cagg_bgw_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. --- --- Setup --- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE OR REPLACE FUNCTION ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(timeout INT = -1, mock_start_time INT = 0) RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; -CREATE OR REPLACE FUNCTION ts_bgw_db_scheduler_test_run(timeout INT = -1, mock_start_time INT = 0) RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; -CREATE OR REPLACE FUNCTION ts_bgw_db_scheduler_test_wait_for_scheduler_finish() RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; -CREATE OR REPLACE FUNCTION ts_bgw_params_create() RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; -CREATE OR REPLACE FUNCTION ts_bgw_params_destroy() RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; -CREATE OR REPLACE FUNCTION ts_bgw_params_reset_time(set_time BIGINT = 0, wait BOOLEAN = false) RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; ---test that this all works under the community license -ALTER DATABASE :TEST_DBNAME SET timescaledb.license_key='Community'; ---create a function with no permissions to execute -CREATE FUNCTION get_constant_no_perms() RETURNS INTEGER LANGUAGE SQL IMMUTABLE AS -$BODY$ - SELECT 10; -$BODY$; -REVOKE EXECUTE ON FUNCTION get_constant_no_perms() FROM PUBLIC; -\set WAIT_ON_JOB 0 -\set IMMEDIATELY_SET_UNTIL 1 -\set WAIT_FOR_OTHER_TO_ADVANCE 2 -CREATE OR REPLACE FUNCTION ts_bgw_params_mock_wait_returns_immediately(new_val INTEGER) RETURNS VOID -AS :MODULE_PATHNAME LANGUAGE C VOLATILE; --- Remove any default jobs, e.g., telemetry -DELETE FROM _timescaledb_config.bgw_job WHERE TRUE; -TRUNCATE _timescaledb_internal.bgw_job_stat; -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER -CREATE TABLE public.bgw_log( - msg_no INT, - mock_time BIGINT, - application_name TEXT, - msg TEXT -); -CREATE VIEW sorted_bgw_log AS - SELECT msg_no, - mock_time, - application_name, - regexp_replace(regexp_replace(msg, '(Wait until|started at|execution time) [0-9]+(\.[0-9]+)?', '\1 (RANDOM)', 'g'), 'background worker "[^"]+"','connection') AS msg - FROM bgw_log ORDER BY mock_time, application_name COLLATE "C", msg_no; -CREATE TABLE public.bgw_dsm_handle_store( - handle BIGINT -); -INSERT INTO public.bgw_dsm_handle_store VALUES (0); -SELECT ts_bgw_params_create(); - ts_bgw_params_create ----------------------- - -(1 row) - -SELECT * FROM _timescaledb_config.bgw_job; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - -SELECT * FROM timescaledb_information.job_stats; - hypertable_schema | hypertable_name | job_id | last_run_started_at | last_successful_finish | last_run_status | job_status | last_run_duration | next_start | total_runs | total_successes | total_failures --------------------+-----------------+--------+---------------------+------------------------+-----------------+------------+-------------------+------------+------------+-----------------+---------------- -(0 rows) - -SELECT * FROM _timescaledb_catalog.continuous_agg; - mat_hypertable_id | raw_hypertable_id | parent_mat_hypertable_id | user_view_schema | user_view_name | partial_view_schema | partial_view_name | bucket_width | direct_view_schema | direct_view_name | materialized_only | finalized --------------------+-------------------+--------------------------+------------------+----------------+---------------------+-------------------+--------------+--------------------+------------------+-------------------+----------- -(0 rows) - --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -psql:include/cagg_bgw_common.sql:76: WARNING: no privileges were granted for "public" -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER -CREATE TABLE test_continuous_agg_table(time int, data int); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('test_continuous_agg_table', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_bgw_common.sql:80: WARNING: distributed hypertable is deprecated -psql:include/cagg_bgw_common.sql:80: NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ----------------------------------------- - (1,public,test_continuous_agg_table,t) -(1 row) - -\else -SELECT create_hypertable('test_continuous_agg_table', 'time', chunk_time_interval => 10); -\endif -CREATE OR REPLACE FUNCTION integer_now_test() returns int LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM test_continuous_agg_table $$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION integer_now_test() returns int LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM test_continuous_agg_table $$; -$DIST$); -\endif -SELECT set_integer_now_func('test_continuous_agg_table', 'integer_now_test'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW test_continuous_agg_view - WITH (timescaledb.continuous, timescaledb.materialized_only=true) - AS SELECT time_bucket('2', time), SUM(data) as value - FROM test_continuous_agg_table - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_continuous_agg_view', NULL, 4::integer, '12 h'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1000 -(1 row) - -SELECT id as raw_table_id FROM _timescaledb_catalog.hypertable WHERE table_name='test_continuous_agg_table' \gset --- min distance from end should be 1 -SELECT mat_hypertable_id, user_view_schema, user_view_name, bucket_width -FROM _timescaledb_catalog.continuous_agg; - mat_hypertable_id | user_view_schema | user_view_name | bucket_width --------------------+------------------+--------------------------+-------------- - 2 | public | test_continuous_agg_view | 2 -(1 row) - -SELECT mat_hypertable_id FROM _timescaledb_catalog.continuous_agg \gset -SELECT id AS job_id FROM _timescaledb_config.bgw_job where hypertable_id=:mat_hypertable_id \gset --- job was created -SELECT * FROM _timescaledb_config.bgw_job where hypertable_id=:mat_hypertable_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+-------------------+-----------+----------------+---------------+---------------+-----------------------------------------------------------------+------------------------+-------------------------------------------+---------- - 1000 | Refresh Continuous Aggregate Policy [1000] | @ 12 hours | @ 0 | -1 | @ 12 hours | _timescaledb_functions | policy_refresh_continuous_aggregate | default_perm_user | t | f | | 2 | {"end_offset": 4, "start_offset": null, "mat_hypertable_id": 2} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | -(1 row) - --- create 10 time buckets -INSERT INTO test_continuous_agg_table - SELECT i, i FROM - (SELECT generate_series(0, 10) as i) AS j; --- no stats -SELECT job_id, next_start, last_finish as until_next, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - ORDER BY job_id; - job_id | next_start | until_next | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------+------------+------------------+------------+-----------------+----------------+--------------- -(0 rows) - --- no data in view -SELECT * FROM test_continuous_agg_view ORDER BY 1; - time_bucket | value --------------+------- -(0 rows) - --- run first time -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - -SELECT * FROM sorted_bgw_log; - msg_no | mock_time | application_name | msg ---------+-----------+--------------------------------------------+------------------------------------------------------------------------------------------------- - 0 | 0 | DB Scheduler | [TESTING] Registered new background worker - 1 | 0 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 0 | Refresh Continuous Aggregate Policy [1000] | refreshing continuous aggregate "test_continuous_agg_view" in window [ -2147483648, 6 ] - 1 | 0 | Refresh Continuous Aggregate Policy [1000] | deleted 0 row(s) from materialization table "_timescaledb_internal._materialized_hypertable_2" - 2 | 0 | Refresh Continuous Aggregate Policy [1000] | inserted 3 row(s) into materialization table "_timescaledb_internal._materialized_hypertable_2" -(5 rows) - -SELECT * FROM _timescaledb_config.bgw_job where id=:job_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+-------------------+-----------+----------------+---------------+---------------+-----------------------------------------------------------------+------------------------+-------------------------------------------+---------- - 1000 | Refresh Continuous Aggregate Policy [1000] | @ 12 hours | @ 0 | -1 | @ 12 hours | _timescaledb_functions | policy_refresh_continuous_aggregate | default_perm_user | t | f | | 2 | {"end_offset": 4, "start_offset": null, "mat_hypertable_id": 2} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | -(1 row) - --- job ran once, successfully -SELECT job_id, next_start-last_finish as until_next, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | until_next | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------+------------------+------------+-----------------+----------------+--------------- - 1000 | @ 12 hours | t | 1 | 1 | 0 | 0 -(1 row) - ---clear log for next run of scheduler. -TRUNCATE public.bgw_log; -CREATE FUNCTION wait_for_timer_to_run(started_at INTEGER, spins INTEGER=:TEST_SPINWAIT_ITERS) RETURNS BOOLEAN LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - num_runs INTEGER; - message TEXT; -BEGIN - select format('[TESTING] Wait until %%, started at %s', started_at) into message; - FOR i in 1..spins - LOOP - SELECT COUNT(*) from bgw_log where msg LIKE message INTO num_runs; - if (num_runs > 0) THEN - RETURN true; - ELSE - PERFORM pg_sleep(0.1); - END IF; - END LOOP; - RETURN false; -END -$BODY$; -CREATE FUNCTION wait_for_job_to_run(job_param_id INTEGER, expected_runs INTEGER, spins INTEGER=:TEST_SPINWAIT_ITERS) RETURNS BOOLEAN LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - num_runs INTEGER; -BEGIN - FOR i in 1..spins - LOOP - SELECT total_successes FROM _timescaledb_internal.bgw_job_stat WHERE job_id=job_param_id INTO num_runs; - if (num_runs = expected_runs) THEN - RETURN true; - ELSEIF (num_runs > expected_runs) THEN - RAISE 'num_runs > expected'; - ELSE - PERFORM pg_sleep(0.1); - END IF; - END LOOP; - RETURN false; -END -$BODY$; ---make sure there is 1 job to start with -SELECT wait_for_job_to_run(:job_id, 1); - wait_for_job_to_run ---------------------- - t -(1 row) - -SELECT ts_bgw_params_mock_wait_returns_immediately(:WAIT_FOR_OTHER_TO_ADVANCE); - ts_bgw_params_mock_wait_returns_immediately ---------------------------------------------- - -(1 row) - ---start the scheduler on 0 time -SELECT ts_bgw_params_reset_time(0, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT ts_bgw_db_scheduler_test_run(extract(epoch from interval '24 hour')::int * 1000, 0); - ts_bgw_db_scheduler_test_run ------------------------------- - -(1 row) - -SELECT wait_for_timer_to_run(0); - wait_for_timer_to_run ------------------------ - t -(1 row) - ---advance to 12:00 so that it runs one more time; now we know the ---scheduler has loaded up the job with the old schedule_interval -SELECT ts_bgw_params_reset_time(extract(epoch from interval '12 hour')::bigint * 1000000, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT wait_for_job_to_run(:job_id, 2); - wait_for_job_to_run ---------------------- - t -(1 row) - ---advance clock 1us to make the scheduler realize the job is done -SELECT ts_bgw_params_reset_time((extract(epoch from interval '12 hour')::bigint * 1000000)+1, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - ---alter the refresh interval and check if next_start is altered -SELECT alter_job(:job_id, schedule_interval => '1m', retry_period => '1m'); - alter_job -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - (1000,"@ 1 min","@ 0",-1,"@ 1 min",t,"{""end_offset"": 4, ""start_offset"": null, ""mat_hypertable_id"": 2}","Sat Jan 01 04:01:00 2000 PST",_timescaledb_functions.policy_refresh_continuous_aggregate_check,f,,) -(1 row) - -SELECT job_id, next_start - last_finish as until_next, total_runs -FROM _timescaledb_internal.bgw_job_stat -WHERE job_id=:job_id;; - job_id | until_next | total_runs ---------+------------+------------ - 1000 | @ 1 min | 2 -(1 row) - ---advance to 12:02, job should have run at 12:01 -SELECT ts_bgw_params_reset_time((extract(epoch from interval '12 hour')::bigint * 1000000)+(extract(epoch from interval '2 minute')::bigint * 1000000), true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT wait_for_job_to_run(:job_id, 3); - wait_for_job_to_run ---------------------- - t -(1 row) - ---next run in 1 minute -SELECT job_id, next_start-last_finish as until_next, total_runs -FROM _timescaledb_internal.bgw_job_stat -WHERE job_id=:job_id; - job_id | until_next | total_runs ---------+------------+------------ - 1000 | @ 1 min | 3 -(1 row) - ---change next run to be after 30s instead -SELECT (next_start - '30s'::interval) AS "NEW_NEXT_START" -FROM _timescaledb_internal.bgw_job_stat -WHERE job_id=:job_id \gset -SELECT alter_job(:job_id, next_start => :'NEW_NEXT_START'); - alter_job -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - (1000,"@ 1 min","@ 0",-1,"@ 1 min",t,"{""end_offset"": 4, ""start_offset"": null, ""mat_hypertable_id"": 2}","Sat Jan 01 04:02:30 2000 PST",_timescaledb_functions.policy_refresh_continuous_aggregate_check,f,,) -(1 row) - -SELECT ts_bgw_params_reset_time((extract(epoch from interval '12 hour')::bigint * 1000000)+(extract(epoch from interval '2 minute 30 seconds')::bigint * 1000000), true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT wait_for_job_to_run(:job_id, 4); - wait_for_job_to_run ---------------------- - t -(1 row) - ---advance clock to quit scheduler -SELECT ts_bgw_params_reset_time(extract(epoch from interval '25 hour')::bigint * 1000000, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -select ts_bgw_db_scheduler_test_wait_for_scheduler_finish(); - ts_bgw_db_scheduler_test_wait_for_scheduler_finish ----------------------------------------------------- - -(1 row) - -SELECT ts_bgw_params_mock_wait_returns_immediately(:WAIT_ON_JOB); - ts_bgw_params_mock_wait_returns_immediately ---------------------------------------------- - -(1 row) - -TRUNCATE public.bgw_log; --- data before 8 -SELECT * FROM test_continuous_agg_view ORDER BY 1; - time_bucket | value --------------+------- - 0 | 1 - 2 | 5 - 4 | 9 -(3 rows) - --- invalidations test by running job multiple times -SELECT ts_bgw_params_reset_time(); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -DROP MATERIALIZED VIEW test_continuous_agg_view; -psql:include/cagg_bgw_common.sql:234: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_3_chunk -CREATE MATERIALIZED VIEW test_continuous_agg_view - WITH (timescaledb.continuous, - timescaledb.materialized_only=true) - AS SELECT time_bucket('2', time), SUM(data) as value - FROM test_continuous_agg_table - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_continuous_agg_view', 100::integer, -2::integer, '12 h'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1001 -(1 row) - -SELECT mat_hypertable_id FROM _timescaledb_catalog.continuous_agg \gset -SELECT id AS job_id FROM _timescaledb_config.bgw_job WHERE hypertable_id=:mat_hypertable_id \gset -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - -SELECT * FROM sorted_bgw_log; - msg_no | mock_time | application_name | msg ---------+-----------+--------------------------------------------+------------------------------------------------------------------------------------------------- - 0 | 0 | DB Scheduler | [TESTING] Registered new background worker - 1 | 0 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 0 | Refresh Continuous Aggregate Policy [1001] | refreshing continuous aggregate "test_continuous_agg_view" in window [ -90, 12 ] - 1 | 0 | Refresh Continuous Aggregate Policy [1001] | deleted 0 row(s) from materialization table "_timescaledb_internal._materialized_hypertable_3" - 2 | 0 | Refresh Continuous Aggregate Policy [1001] | inserted 6 row(s) into materialization table "_timescaledb_internal._materialized_hypertable_3" -(5 rows) - --- job ran once, successfully -SELECT job_id, last_finish - next_start as until_next, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | until_next | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+----------------+------------------+------------+-----------------+----------------+--------------- - 1001 | @ 12 hours ago | t | 1 | 1 | 0 | 0 -(1 row) - --- should have refreshed everything we have so far -SELECT * FROM test_continuous_agg_view ORDER BY 1; - time_bucket | value --------------+------- - 0 | 1 - 2 | 5 - 4 | 9 - 6 | 13 - 8 | 17 - 10 | 10 -(6 rows) - --- invalidate some data -UPDATE test_continuous_agg_table -SET data = 11 WHERE time = 6; ---advance time by 12h so that job runs one more time -SELECT ts_bgw_params_reset_time(extract(epoch from interval '12 hour')::bigint * 1000000, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25, 25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - -SELECT * FROM sorted_bgw_log; - msg_no | mock_time | application_name | msg ---------+-------------+--------------------------------------------+------------------------------------------------------------------------------------------------- - 0 | 0 | DB Scheduler | [TESTING] Registered new background worker - 1 | 0 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 0 | Refresh Continuous Aggregate Policy [1001] | refreshing continuous aggregate "test_continuous_agg_view" in window [ -90, 12 ] - 1 | 0 | Refresh Continuous Aggregate Policy [1001] | deleted 0 row(s) from materialization table "_timescaledb_internal._materialized_hypertable_3" - 2 | 0 | Refresh Continuous Aggregate Policy [1001] | inserted 6 row(s) into materialization table "_timescaledb_internal._materialized_hypertable_3" - 0 | 43200000000 | DB Scheduler | [TESTING] Registered new background worker - 1 | 43200000000 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 43200000000 | Refresh Continuous Aggregate Policy [1001] | refreshing continuous aggregate "test_continuous_agg_view" in window [ -90, 12 ] - 1 | 43200000000 | Refresh Continuous Aggregate Policy [1001] | deleted 1 row(s) from materialization table "_timescaledb_internal._materialized_hypertable_3" - 2 | 43200000000 | Refresh Continuous Aggregate Policy [1001] | inserted 1 row(s) into materialization table "_timescaledb_internal._materialized_hypertable_3" -(10 rows) - -SELECT job_id, next_start - last_finish as until_next, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | until_next | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------+------------------+------------+-----------------+----------------+--------------- - 1001 | @ 12 hours | t | 2 | 2 | 0 | 0 -(1 row) - --- should have updated data for time=6 -SELECT * FROM test_continuous_agg_view ORDER BY 1; - time_bucket | value --------------+------- - 0 | 1 - 2 | 5 - 4 | 9 - 6 | 18 - 8 | 17 - 10 | 10 -(6 rows) - -\x on ---check the information views -- -select view_name, view_owner, materialization_hypertable_schema, materialization_hypertable_name -from timescaledb_information.continuous_aggregates -where view_name::text like '%test_continuous_agg_view'; --[ RECORD 1 ]---------------------+--------------------------- -view_name | test_continuous_agg_view -view_owner | default_perm_user -materialization_hypertable_schema | _timescaledb_internal -materialization_hypertable_name | _materialized_hypertable_3 - -select view_name, view_definition from timescaledb_information.continuous_aggregates -where view_name::text like '%test_continuous_agg_view'; --[ RECORD 1 ]---+------------------------------------------------------------------------- -view_name | test_continuous_agg_view -view_definition | SELECT time_bucket(2, test_continuous_agg_table."time") AS time_bucket,+ - | sum(test_continuous_agg_table.data) AS value + - | FROM test_continuous_agg_table + - | GROUP BY (time_bucket(2, test_continuous_agg_table."time")); - -select job_status, last_run_duration -from timescaledb_information.job_stats ps, timescaledb_information.continuous_aggregates cagg -where cagg.view_name::text like '%test_continuous_agg_view' -and cagg.materialization_hypertable_name = ps.hypertable_name; --[ RECORD 1 ]-----+---------- -job_status | Scheduled -last_run_duration | - -\x off -DROP MATERIALIZED VIEW test_continuous_agg_view; -psql:include/cagg_bgw_common.sql:294: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_4_chunk ---create a view with a function that it has no permission to execute -CREATE MATERIALIZED VIEW test_continuous_agg_view - WITH (timescaledb.continuous, - timescaledb.materialized_only=true) - AS SELECT time_bucket('2', time), SUM(data) as value, get_constant_no_perms() - FROM test_continuous_agg_table - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_continuous_agg_view', 100::integer, -2::integer, '12 h'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1002 -(1 row) - -SELECT id AS job_id FROM _timescaledb_config.bgw_job ORDER BY id desc limit 1 \gset -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - --- job fails -SELECT job_id, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------------+------------+-----------------+----------------+--------------- - 1002 | f | 1 | 0 | 1 | 0 -(1 row) - -DROP MATERIALIZED VIEW test_continuous_agg_view; ---advance clock to quit scheduler -SELECT ts_bgw_params_reset_time(extract(epoch from interval '25 hour')::bigint * 1000000, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -select ts_bgw_db_scheduler_test_wait_for_scheduler_finish(); - ts_bgw_db_scheduler_test_wait_for_scheduler_finish ----------------------------------------------------- - -(1 row) - -SELECT ts_bgw_params_mock_wait_returns_immediately(:WAIT_ON_JOB); - ts_bgw_params_mock_wait_returns_immediately ---------------------------------------------- - -(1 row) - ---clear log for next run of the scheduler -TRUNCATE public.bgw_log; -SELECT ts_bgw_params_reset_time(); - ts_bgw_params_reset_time --------------------------- - -(1 row) - --- --- Test creating continuous aggregate with a user that is the non-owner of the raw table --- -CREATE TABLE test_continuous_agg_table_w_grant(time int, data int); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('test_continuous_agg_table_w_grant', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_bgw_common.sql:330: WARNING: distributed hypertable is deprecated -psql:include/cagg_bgw_common.sql:330: NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ------------------------------------------------- - (5,public,test_continuous_agg_table_w_grant,t) -(1 row) - -\else -SELECT create_hypertable('test_continuous_agg_table_w_grant', 'time', chunk_time_interval => 10); -\endif -CREATE OR REPLACE FUNCTION integer_now_test1() returns int LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM test_continuous_agg_table_w_grant $$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION integer_now_test1() returns int LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM test_continuous_agg_table_w_grant $$; -$DIST$); -\endif -SELECT set_integer_now_func('test_continuous_agg_table_w_grant', 'integer_now_test1'); - set_integer_now_func ----------------------- - -(1 row) - -GRANT SELECT, TRIGGER ON test_continuous_agg_table_w_grant TO public; -INSERT INTO test_continuous_agg_table_w_grant - SELECT 1 , 1; -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2 --- make sure view can be created -CREATE MATERIALIZED VIEW test_continuous_agg_view_user_2 - WITH ( timescaledb.continuous, - timescaledb.materialized_only=true) - AS SELECT time_bucket('2', time), SUM(data) as value - FROM test_continuous_agg_table_w_grant - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_continuous_agg_view_user_2', NULL, -2::integer, '12 h'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1003 -(1 row) - -SELECT id AS job_id FROM _timescaledb_config.bgw_job ORDER BY id desc limit 1 \gset -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - -SELECT id, owner FROM _timescaledb_config.bgw_job WHERE id = :job_id ; - id | owner -------+--------------------- - 1003 | default_perm_user_2 -(1 row) - -SELECT job_id, next_start - last_finish as until_next, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | until_next | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------+------------------+------------+-----------------+----------------+--------------- - 1003 | @ 12 hours | t | 1 | 1 | 0 | 0 -(1 row) - ---view is populated -SELECT * FROM test_continuous_agg_view_user_2 ORDER BY 1; - time_bucket | value --------------+------- - 0 | 1 -(1 row) - -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER ---revoke permissions from the continuous agg view owner to select from raw table ---no further updates to cont agg should happen -REVOKE SELECT ON test_continuous_agg_table_w_grant FROM public; ---add new data to table -INSERT INTO test_continuous_agg_table_w_grant VALUES(5,1); -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2 ---advance time by 12h so that job tries to run one more time -SELECT ts_bgw_params_reset_time(extract(epoch from interval '12 hour')::bigint * 1000000, true); - ts_bgw_params_reset_time --------------------------- - -(1 row) - -SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25, 25); - ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish ------------------------------------------------------------- - -(1 row) - ---should show a failing execution because no longer has permissions (due to lack of permission on partial view owner's part) -SELECT job_id, last_run_success, total_runs, total_successes, total_failures, total_crashes - FROM _timescaledb_internal.bgw_job_stat - where job_id=:job_id; - job_id | last_run_success | total_runs | total_successes | total_failures | total_crashes ---------+------------------+------------+-----------------+----------------+--------------- - 1003 | f | 2 | 1 | 1 | 0 -(1 row) - ---view was NOT updated; but the old stuff is still there -SELECT * FROM test_continuous_agg_view_user_2; - time_bucket | value --------------+------- - 0 | 1 -(1 row) - -\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER -SELECT * from sorted_bgw_log; - msg_no | mock_time | application_name | msg ---------+-------------+--------------------------------------------+------------------------------------------------------------------------------------------------- - 0 | 0 | DB Scheduler | [TESTING] Registered new background worker - 1 | 0 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 0 | Refresh Continuous Aggregate Policy [1003] | refreshing continuous aggregate "test_continuous_agg_view_user_2" in window [ -2147483648, 2 ] - 1 | 0 | Refresh Continuous Aggregate Policy [1003] | deleted 0 row(s) from materialization table "_timescaledb_internal._materialized_hypertable_6" - 2 | 0 | Refresh Continuous Aggregate Policy [1003] | inserted 1 row(s) into materialization table "_timescaledb_internal._materialized_hypertable_6" - 0 | 43200000000 | DB Scheduler | [TESTING] Registered new background worker - 1 | 43200000000 | DB Scheduler | [TESTING] Wait until (RANDOM), started at (RANDOM) - 0 | 43200000000 | Refresh Continuous Aggregate Policy [1003] | job 1003 threw an error - 1 | 43200000000 | Refresh Continuous Aggregate Policy [1003] | permission denied for table test_continuous_agg_table_w_grant -(9 rows) - --- Count the number of continuous aggregate policies -SELECT count(*) FROM _timescaledb_config.bgw_job - WHERE proc_schema = '_timescaledb_functions' - AND proc_name = 'policy_refresh_continuous_aggregate'; - count -------- - 1 -(1 row) - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_ddl_dist_ht.out b/tsl/test/expected/cagg_ddl_dist_ht.out deleted file mode 100644 index f8430fde30c..00000000000 --- a/tsl/test/expected/cagg_ddl_dist_ht.out +++ /dev/null @@ -1,2233 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_cagg_ddl_dist_ht_1 | db_cagg_ddl_dist_ht_1 | t | t | t - db_cagg_ddl_dist_ht_2 | db_cagg_ddl_dist_ht_2 | t | t | t - db_cagg_ddl_dist_ht_3 | db_cagg_ddl_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\set IS_DISTRIBUTED TRUE -\ir include/cagg_ddl_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. --- Set this variable to avoid using a hard-coded path each time query --- results are compared -\set QUERY_RESULT_TEST_EQUAL_RELPATH '../../../../test/sql/include/query_result_test_equal.sql' -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; ---DDL commands on continuous aggregates -CREATE TABLE conditions ( - timec TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - temperature integer NULL, - humidity DOUBLE PRECISION NULL, - timemeasure TIMESTAMPTZ, - timeinterval INTERVAL -); -\if :IS_DISTRIBUTED -SELECT table_name FROM create_distributed_hypertable('conditions', 'timec', replication_factor => 2); -psql:include/cagg_ddl_common.sql:29: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - -\else -SELECT table_name FROM create_hypertable('conditions', 'timec'); -\endif --- schema tests -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER --- drop if the tablespace1 and/or tablespace2 exists -SET client_min_messages TO error; -DROP TABLESPACE IF EXISTS tablespace1; -DROP TABLESPACE IF EXISTS tablespace2; -RESET client_min_messages; -CREATE TABLESPACE tablespace1 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE1_PATH; -CREATE TABLESPACE tablespace2 OWNER :ROLE_DEFAULT_PERM_USER LOCATION :TEST_TABLESPACE2_PATH; -CREATE SCHEMA rename_schema; -GRANT ALL ON SCHEMA rename_schema TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -CREATE TABLE foo(time TIMESTAMPTZ NOT NULL, data INTEGER); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('foo', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:53: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,foo,t) -(1 row) - -\else -SELECT create_hypertable('foo', 'time'); -\endif -CREATE MATERIALIZED VIEW rename_test - WITH ( timescaledb.continuous, timescaledb.materialized_only=true) -AS SELECT time_bucket('1week', time), COUNT(data) - FROM foo - GROUP BY 1 WITH NO DATA; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+-----------------------+------------------- - public | rename_test | _timescaledb_internal | _partial_view_3 -(1 row) - -ALTER MATERIALIZED VIEW rename_test SET SCHEMA rename_schema; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+-----------------------+------------------- - rename_schema | rename_test | _timescaledb_internal | _partial_view_3 -(1 row) - -SELECT ca.raw_hypertable_id as "RAW_HYPERTABLE_ID", - h.schema_name AS "MAT_SCHEMA_NAME", - h.table_name AS "MAT_TABLE_NAME", - partial_view_name as "PART_VIEW_NAME", - partial_view_schema as "PART_VIEW_SCHEMA", - direct_view_name as "DIR_VIEW_NAME", - direct_view_schema as "DIR_VIEW_SCHEMA" -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON(h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'rename_test' -\gset -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -ALTER VIEW :"PART_VIEW_SCHEMA".:"PART_VIEW_NAME" SET SCHEMA public; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+---------------------+------------------- - rename_schema | rename_test | public | _partial_view_3 -(1 row) - ---alter direct view schema -SELECT user_view_schema, user_view_name, direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | direct_view_schema | direct_view_name -------------------+----------------+-----------------------+------------------ - rename_schema | rename_test | _timescaledb_internal | _direct_view_3 -(1 row) - -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -ALTER VIEW :"DIR_VIEW_SCHEMA".:"DIR_VIEW_NAME" SET SCHEMA public; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name, - direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name | direct_view_schema | direct_view_name -------------------+----------------+---------------------+-------------------+--------------------+------------------ - rename_schema | rename_test | public | _partial_view_3 | public | _direct_view_3 -(1 row) - -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -ALTER SCHEMA rename_schema RENAME TO new_name_schema; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name, - direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name | direct_view_schema | direct_view_name -------------------+----------------+---------------------+-------------------+--------------------+------------------ - new_name_schema | rename_test | public | _partial_view_3 | public | _direct_view_3 -(1 row) - -ALTER VIEW :"PART_VIEW_NAME" SET SCHEMA new_name_schema; -ALTER VIEW :"DIR_VIEW_NAME" SET SCHEMA new_name_schema; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name, - direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name | direct_view_schema | direct_view_name -------------------+----------------+---------------------+-------------------+--------------------+------------------ - new_name_schema | rename_test | new_name_schema | _partial_view_3 | new_name_schema | _direct_view_3 -(1 row) - -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -ALTER SCHEMA new_name_schema RENAME TO foo_name_schema; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+---------------------+------------------- - foo_name_schema | rename_test | foo_name_schema | _partial_view_3 -(1 row) - -ALTER MATERIALIZED VIEW foo_name_schema.rename_test SET SCHEMA public; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+---------------------+------------------- - public | rename_test | foo_name_schema | _partial_view_3 -(1 row) - -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -ALTER SCHEMA foo_name_schema RENAME TO rename_schema; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SET client_min_messages TO NOTICE; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+----------------+---------------------+------------------- - public | rename_test | rename_schema | _partial_view_3 -(1 row) - -ALTER MATERIALIZED VIEW rename_test RENAME TO rename_c_aggregate; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name -------------------+--------------------+---------------------+------------------- - public | rename_c_aggregate | rename_schema | _partial_view_3 -(1 row) - -SELECT * FROM rename_c_aggregate; - time_bucket | count --------------+------- -(0 rows) - -ALTER VIEW rename_schema.:"PART_VIEW_NAME" RENAME TO partial_view; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name, - direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name | direct_view_schema | direct_view_name -------------------+--------------------+---------------------+-------------------+--------------------+------------------ - public | rename_c_aggregate | rename_schema | partial_view | rename_schema | _direct_view_3 -(1 row) - ---rename direct view -ALTER VIEW rename_schema.:"DIR_VIEW_NAME" RENAME TO direct_view; -SELECT user_view_schema, user_view_name, partial_view_schema, partial_view_name, - direct_view_schema, direct_view_name - FROM _timescaledb_catalog.continuous_agg; - user_view_schema | user_view_name | partial_view_schema | partial_view_name | direct_view_schema | direct_view_name -------------------+--------------------+---------------------+-------------------+--------------------+------------------ - public | rename_c_aggregate | rename_schema | partial_view | rename_schema | direct_view -(1 row) - --- drop_chunks tests -DROP TABLE conditions CASCADE; -DROP TABLE foo CASCADE; -psql:include/cagg_ddl_common.sql:166: NOTICE: drop cascades to 2 other objects -CREATE TABLE drop_chunks_table(time BIGINT NOT NULL, data INTEGER); -\if :IS_DISTRIBUTED -SELECT hypertable_id AS drop_chunks_table_id - FROM create_distributed_hypertable('drop_chunks_table', 'time', chunk_time_interval => 10, replication_factor => 2) \gset -psql:include/cagg_ddl_common.sql:171: WARNING: distributed hypertable is deprecated -\else -SELECT hypertable_id AS drop_chunks_table_id - FROM create_hypertable('drop_chunks_table', 'time', chunk_time_interval => 10) \gset -\endif -CREATE OR REPLACE FUNCTION integer_now_test() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table $$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION integer_now_test() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table $$; -$DIST$); -\endif -SELECT set_integer_now_func('drop_chunks_table', 'integer_now_test'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW drop_chunks_view - WITH ( - timescaledb.continuous, - timescaledb.materialized_only=true - ) -AS SELECT time_bucket('5', time), COUNT(data) - FROM drop_chunks_table - GROUP BY 1 WITH NO DATA; -SELECT format('%I.%I', schema_name, table_name) AS drop_chunks_mat_table, - schema_name AS drop_chunks_mat_schema, - table_name AS drop_chunks_mat_table_name - FROM _timescaledb_catalog.hypertable, _timescaledb_catalog.continuous_agg - WHERE _timescaledb_catalog.continuous_agg.raw_hypertable_id = :drop_chunks_table_id - AND _timescaledb_catalog.hypertable.id = _timescaledb_catalog.continuous_agg.mat_hypertable_id \gset --- create 3 chunks, with 3 time bucket -INSERT INTO drop_chunks_table SELECT i, i FROM generate_series(0, 29) AS i; --- Only refresh up to bucket 15 initially. Matches the old refresh --- behavior that didn't materialize everything -CALL refresh_continuous_aggregate('drop_chunks_view', 0, 15); -SELECT count(c) FROM show_chunks('drop_chunks_table') AS c; - count -------- - 3 -(1 row) - -SELECT count(c) FROM show_chunks('drop_chunks_view') AS c; - count -------- - 1 -(1 row) - -SELECT * FROM drop_chunks_view ORDER BY 1; - time_bucket | count --------------+------- - 0 | 5 - 5 | 5 - 10 | 5 -(3 rows) - --- cannot drop directly from the materialization table without specifying --- cont. aggregate view name explicitly -\set ON_ERROR_STOP 0 -SELECT drop_chunks(:'drop_chunks_mat_table', - newer_than => -20, - verbose => true); -psql:include/cagg_ddl_common.sql:218: ERROR: operation not supported on materialized hypertable -\set ON_ERROR_STOP 1 -SELECT count(c) FROM show_chunks('drop_chunks_table') AS c; - count -------- - 3 -(1 row) - -SELECT count(c) FROM show_chunks('drop_chunks_view') AS c; - count -------- - 1 -(1 row) - -SELECT * FROM drop_chunks_view ORDER BY 1; - time_bucket | count --------------+------- - 0 | 5 - 5 | 5 - 10 | 5 -(3 rows) - --- drop chunks when the chunksize and time_bucket aren't aligned -DROP TABLE drop_chunks_table CASCADE; -psql:include/cagg_ddl_common.sql:227: NOTICE: drop cascades to 2 other objects -psql:include/cagg_ddl_common.sql:227: NOTICE: drop cascades to table _timescaledb_internal._hyper_5_4_chunk -CREATE TABLE drop_chunks_table_u(time BIGINT NOT NULL, data INTEGER); -\if :IS_DISTRIBUTED -SELECT hypertable_id AS drop_chunks_table_u_id - FROM create_distributed_hypertable('drop_chunks_table_u', 'time', chunk_time_interval => 7, replication_factor => 2) \gset -psql:include/cagg_ddl_common.sql:232: WARNING: distributed hypertable is deprecated -\else -SELECT hypertable_id AS drop_chunks_table_u_id - FROM create_hypertable('drop_chunks_table_u', 'time', chunk_time_interval => 7) \gset -\endif -CREATE OR REPLACE FUNCTION integer_now_test1() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table_u $$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION integer_now_test1() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table_u $$; -$DIST$); -\endif -SELECT set_integer_now_func('drop_chunks_table_u', 'integer_now_test1'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW drop_chunks_view - WITH ( - timescaledb.continuous, - timescaledb.materialized_only=true - ) -AS SELECT time_bucket('3', time), COUNT(data) - FROM drop_chunks_table_u - GROUP BY 1 WITH NO DATA; -SELECT format('%I.%I', schema_name, table_name) AS drop_chunks_mat_table_u, - schema_name AS drop_chunks_mat_schema, - table_name AS drop_chunks_mat_table_u_name - FROM _timescaledb_catalog.hypertable, _timescaledb_catalog.continuous_agg - WHERE _timescaledb_catalog.continuous_agg.raw_hypertable_id = :drop_chunks_table_u_id - AND _timescaledb_catalog.hypertable.id = _timescaledb_catalog.continuous_agg.mat_hypertable_id \gset --- create 3 chunks, with 3 time bucket -INSERT INTO drop_chunks_table_u SELECT i, i FROM generate_series(0, 21) AS i; --- Refresh up to bucket 15 to match old materializer behavior -CALL refresh_continuous_aggregate('drop_chunks_view', 0, 15); -SELECT count(c) FROM show_chunks('drop_chunks_table_u') AS c; - count -------- - 4 -(1 row) - -SELECT count(c) FROM show_chunks('drop_chunks_view') AS c; - count -------- - 1 -(1 row) - -SELECT * FROM drop_chunks_view ORDER BY 1; - time_bucket | count --------------+------- - 0 | 3 - 3 | 3 - 6 | 3 - 9 | 3 - 12 | 3 -(5 rows) - --- TRUNCATE test --- Can truncate regular hypertables that have caggs -TRUNCATE drop_chunks_table_u; -\set ON_ERROR_STOP 0 --- Can't truncate materialized hypertables directly -TRUNCATE :drop_chunks_mat_table_u; -psql:include/cagg_ddl_common.sql:276: ERROR: cannot TRUNCATE a hypertable underlying a continuous aggregate -\set ON_ERROR_STOP 1 --- Check that we don't interfere with TRUNCATE of normal table and --- partitioned table -CREATE TABLE truncate (value int); -INSERT INTO truncate VALUES (1), (2); -TRUNCATE truncate; -SELECT * FROM truncate; - value -------- -(0 rows) - -CREATE TABLE truncate_partitioned (value int) - PARTITION BY RANGE(value); -CREATE TABLE truncate_p1 PARTITION OF truncate_partitioned - FOR VALUES FROM (1) TO (3); -INSERT INTO truncate_partitioned VALUES (1), (2); -TRUNCATE truncate_partitioned; -SELECT * FROM truncate_partitioned; - value -------- -(0 rows) - --- ALTER TABLE tests -\set ON_ERROR_STOP 0 --- test a variety of ALTER TABLE statements -ALTER TABLE :drop_chunks_mat_table_u RENAME time_bucket TO bad_name; -psql:include/cagg_ddl_common.sql:296: ERROR: renaming columns on materialization tables is not supported -ALTER TABLE :drop_chunks_mat_table_u ADD UNIQUE(time_bucket); -psql:include/cagg_ddl_common.sql:297: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u SET UNLOGGED; -psql:include/cagg_ddl_common.sql:298: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u ENABLE ROW LEVEL SECURITY; -psql:include/cagg_ddl_common.sql:299: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u ADD COLUMN fizzle INTEGER; -psql:include/cagg_ddl_common.sql:300: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u DROP COLUMN time_bucket; -psql:include/cagg_ddl_common.sql:301: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u ALTER COLUMN time_bucket DROP NOT NULL; -psql:include/cagg_ddl_common.sql:302: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u ALTER COLUMN time_bucket SET DEFAULT 1; -psql:include/cagg_ddl_common.sql:303: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u ALTER COLUMN time_bucket SET STORAGE EXTERNAL; -psql:include/cagg_ddl_common.sql:304: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u DISABLE TRIGGER ALL; -psql:include/cagg_ddl_common.sql:305: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u SET TABLESPACE foo; -psql:include/cagg_ddl_common.sql:306: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u NOT OF; -psql:include/cagg_ddl_common.sql:307: ERROR: operation not supported on materialization tables -ALTER TABLE :drop_chunks_mat_table_u OWNER TO CURRENT_USER; -psql:include/cagg_ddl_common.sql:308: ERROR: operation not supported on materialization tables -\set ON_ERROR_STOP 1 -ALTER TABLE :drop_chunks_mat_table_u SET SCHEMA public; -ALTER TABLE :drop_chunks_mat_table_u_name RENAME TO new_name; -SET ROLE :ROLE_DEFAULT_PERM_USER; -SET client_min_messages TO NOTICE; -SELECT * FROM new_name; - time_bucket | count --------------+------- - 0 | 3 - 3 | 3 - 6 | 3 - 9 | 3 - 12 | 3 -(5 rows) - -SELECT * FROM drop_chunks_view ORDER BY 1; - time_bucket | count --------------+------- - 0 | 3 - 3 | 3 - 6 | 3 - 9 | 3 - 12 | 3 -(5 rows) - -\set ON_ERROR_STOP 0 --- no continuous aggregates on a continuous aggregate materialization table -CREATE MATERIALIZED VIEW new_name_view - WITH ( - timescaledb.continuous, - timescaledb.materialized_only=true - ) -AS SELECT time_bucket('6', time_bucket), COUNT("count") - FROM new_name - GROUP BY 1 WITH NO DATA; -psql:include/cagg_ddl_common.sql:331: ERROR: hypertable is a continuous aggregate materialization table -\set ON_ERROR_STOP 1 -CREATE TABLE metrics(time timestamptz NOT NULL, device_id int, v1 float, v2 float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('metrics', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:336: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (8,public,metrics,t) -(1 row) - -\else -SELECT create_hypertable('metrics','time'); -\endif -INSERT INTO metrics SELECT generate_series('2000-01-01'::timestamptz,'2000-01-10','1m'),1,0.25,0.75; --- check expressions in view definition -CREATE MATERIALIZED VIEW cagg_expr - WITH (timescaledb.continuous, timescaledb.materialized_only=true) -AS -SELECT - time_bucket('1d', time) AS time, - 'Const'::text AS Const, - 4.3::numeric AS "numeric", - first(metrics,time), - CASE WHEN true THEN 'foo' ELSE 'bar' END, - COALESCE(NULL,'coalesce'), - avg(v1) + avg(v2) AS avg1, - avg(v1+v2) AS avg2 -FROM metrics -GROUP BY 1 WITH NO DATA; -CALL refresh_continuous_aggregate('cagg_expr', NULL, NULL); -SELECT * FROM cagg_expr ORDER BY time LIMIT 5; - time | const | numeric | first | case | coalesce | avg1 | avg2 -------------------------------+-------+---------+----------------------------------------------+------+----------+------+------ - Fri Dec 31 16:00:00 1999 PST | Const | 4.3 | ("Sat Jan 01 00:00:00 2000 PST",1,0.25,0.75) | foo | coalesce | 1 | 1 - Sat Jan 01 16:00:00 2000 PST | Const | 4.3 | ("Sat Jan 01 16:00:00 2000 PST",1,0.25,0.75) | foo | coalesce | 1 | 1 - Sun Jan 02 16:00:00 2000 PST | Const | 4.3 | ("Sun Jan 02 16:00:00 2000 PST",1,0.25,0.75) | foo | coalesce | 1 | 1 - Mon Jan 03 16:00:00 2000 PST | Const | 4.3 | ("Mon Jan 03 16:00:00 2000 PST",1,0.25,0.75) | foo | coalesce | 1 | 1 - Tue Jan 04 16:00:00 2000 PST | Const | 4.3 | ("Tue Jan 04 16:00:00 2000 PST",1,0.25,0.75) | foo | coalesce | 1 | 1 -(5 rows) - ---test materialization of invalidation before drop -DROP TABLE IF EXISTS drop_chunks_table CASCADE; -psql:include/cagg_ddl_common.sql:363: NOTICE: table "drop_chunks_table" does not exist, skipping -DROP TABLE IF EXISTS drop_chunks_table_u CASCADE; -psql:include/cagg_ddl_common.sql:364: NOTICE: drop cascades to 2 other objects -psql:include/cagg_ddl_common.sql:364: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_9_chunk -CREATE TABLE drop_chunks_table(time BIGINT NOT NULL, data INTEGER); -\if :IS_DISTRIBUTED -SELECT hypertable_id AS drop_chunks_table_nid - FROM create_distributed_hypertable('drop_chunks_table', 'time', chunk_time_interval => 10, replication_factor => 2) \gset -psql:include/cagg_ddl_common.sql:369: WARNING: distributed hypertable is deprecated -\else -SELECT hypertable_id AS drop_chunks_table_nid - FROM create_hypertable('drop_chunks_table', 'time', chunk_time_interval => 10) \gset -\endif -CREATE OR REPLACE FUNCTION integer_now_test2() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table $$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION integer_now_test2() returns bigint LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), bigint '0') FROM drop_chunks_table $$; -$DIST$); -\endif -SELECT set_integer_now_func('drop_chunks_table', 'integer_now_test2'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW drop_chunks_view - WITH ( - timescaledb.continuous, - timescaledb.materialized_only=true - ) -AS SELECT time_bucket('5', time), max(data) - FROM drop_chunks_table - GROUP BY 1 WITH NO DATA; -INSERT INTO drop_chunks_table SELECT i, i FROM generate_series(0, 20) AS i; ---dropping chunks will process the invalidations -SELECT drop_chunks('drop_chunks_table', older_than => (integer_now_test2()-9)); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_13_chunk -(1 row) - -SELECT * FROM drop_chunks_table ORDER BY time ASC limit 1; - time | data -------+------ - 10 | 10 -(1 row) - -INSERT INTO drop_chunks_table SELECT i, i FROM generate_series(20, 35) AS i; -CALL refresh_continuous_aggregate('drop_chunks_view', 10, 40); ---this will be seen after the drop its within the invalidation window and will be dropped -INSERT INTO drop_chunks_table VALUES (26, 100); ---this will not be processed by the drop since chunk 30-39 is not dropped but will be seen after refresh ---shows that the drop doesn't do more work than necessary -INSERT INTO drop_chunks_table VALUES (31, 200); ---move the time up to 39 -INSERT INTO drop_chunks_table SELECT i, i FROM generate_series(35, 39) AS i; ---the chunks and ranges we have thus far -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = 'drop_chunks_table'; - chunk_name | range_start_integer | range_end_integer --------------------------+---------------------+------------------- - _dist_hyper_10_14_chunk | 10 | 20 - _dist_hyper_10_15_chunk | 20 | 30 - _dist_hyper_10_16_chunk | 30 | 40 -(3 rows) - ---the invalidation on 25 not yet seen -SELECT * FROM drop_chunks_view ORDER BY time_bucket DESC; - time_bucket | max --------------+----- - 35 | 35 - 30 | 34 - 25 | 29 - 20 | 24 - 15 | 19 - 10 | 14 -(6 rows) - ---refresh to process the invalidations and then drop -CALL refresh_continuous_aggregate('drop_chunks_view', NULL, (integer_now_test2()-9)); -SELECT drop_chunks('drop_chunks_table', older_than => (integer_now_test2()-9)); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_14_chunk - _timescaledb_internal._dist_hyper_10_15_chunk -(2 rows) - ---new values on 25 now seen in view -SELECT * FROM drop_chunks_view ORDER BY time_bucket DESC; - time_bucket | max --------------+----- - 35 | 35 - 30 | 34 - 25 | 100 - 20 | 24 - 15 | 19 - 10 | 14 -(6 rows) - ---earliest datapoint now in table -SELECT * FROM drop_chunks_table ORDER BY time ASC limit 1; - time | data -------+------ - 30 | 30 -(1 row) - ---we see the chunks row with the dropped flags set; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk where dropped; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-------------------------+---------------------+---------+--------+----------- - 13 | 10 | _timescaledb_internal | _dist_hyper_10_13_chunk | | t | 0 | f - 14 | 10 | _timescaledb_internal | _dist_hyper_10_14_chunk | | t | 0 | f - 15 | 10 | _timescaledb_internal | _dist_hyper_10_15_chunk | | t | 0 | f -(3 rows) - ---still see data in the view -SELECT * FROM drop_chunks_view WHERE time_bucket < (integer_now_test2()-9) ORDER BY time_bucket DESC; - time_bucket | max --------------+----- - 25 | 100 - 20 | 24 - 15 | 19 - 10 | 14 -(4 rows) - ---no data but covers dropped chunks -SELECT * FROM drop_chunks_table WHERE time < (integer_now_test2()-9) ORDER BY time DESC; - time | data -------+------ -(0 rows) - ---recreate the dropped chunk -INSERT INTO drop_chunks_table SELECT i, i FROM generate_series(0, 20) AS i; ---see data from recreated region -SELECT * FROM drop_chunks_table WHERE time < (integer_now_test2()-9) ORDER BY time DESC; - time | data -------+------ - 20 | 20 - 19 | 19 - 18 | 18 - 17 | 17 - 16 | 16 - 15 | 15 - 14 | 14 - 13 | 13 - 12 | 12 - 11 | 11 - 10 | 10 - 9 | 9 - 8 | 8 - 7 | 7 - 6 | 6 - 5 | 5 - 4 | 4 - 3 | 3 - 2 | 2 - 1 | 1 - 0 | 0 -(21 rows) - ---should show chunk with old name and old ranges -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = 'drop_chunks_table' -ORDER BY range_start_integer; - chunk_name | range_start_integer | range_end_integer --------------------------+---------------------+------------------- - _dist_hyper_10_13_chunk | 0 | 10 - _dist_hyper_10_14_chunk | 10 | 20 - _dist_hyper_10_15_chunk | 20 | 30 - _dist_hyper_10_16_chunk | 30 | 40 -(4 rows) - ---We dropped everything up to the bucket starting at 30 and then ---inserted new data up to and including time 20. Therefore, the ---dropped data should stay the same as long as we only refresh ---buckets that have non-dropped data. -CALL refresh_continuous_aggregate('drop_chunks_view', 30, 40); -SELECT * FROM drop_chunks_view ORDER BY time_bucket DESC; - time_bucket | max --------------+----- - 35 | 39 - 30 | 200 - 25 | 100 - 20 | 24 - 15 | 19 - 10 | 14 -(6 rows) - -SELECT format('%I.%I', schema_name, table_name) AS drop_chunks_mat_tablen, - schema_name AS drop_chunks_mat_schema, - table_name AS drop_chunks_mat_table_name - FROM _timescaledb_catalog.hypertable, _timescaledb_catalog.continuous_agg - WHERE _timescaledb_catalog.continuous_agg.raw_hypertable_id = :drop_chunks_table_nid - AND _timescaledb_catalog.hypertable.id = _timescaledb_catalog.continuous_agg.mat_hypertable_id \gset --- TEST drop chunks from continuous aggregates by specifying view name -SELECT drop_chunks('drop_chunks_view', - newer_than => -20, - verbose => true); -psql:include/cagg_ddl_common.sql:459: INFO: dropping chunk _timescaledb_internal._hyper_11_17_chunk - drop_chunks ------------------------------------------- - _timescaledb_internal._hyper_11_17_chunk -(1 row) - --- Test that we cannot drop chunks when specifying materialized --- hypertable -INSERT INTO drop_chunks_table SELECT generate_series(45, 55), 500; -CALL refresh_continuous_aggregate('drop_chunks_view', 45, 55); -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = :'drop_chunks_mat_table_name' ORDER BY range_start_integer; - chunk_name | range_start_integer | range_end_integer ---------------------+---------------------+------------------- - _hyper_11_20_chunk | 0 | 100 -(1 row) - -\set ON_ERROR_STOP 0 -\set VERBOSITY default -SELECT drop_chunks(:'drop_chunks_mat_tablen', older_than => 60); -psql:include/cagg_ddl_common.sql:471: ERROR: operation not supported on materialized hypertable -DETAIL: Hypertable "_materialized_hypertable_11" is a materialized hypertable. -HINT: Try the operation on the continuous aggregate instead. -\set VERBOSITY terse -\set ON_ERROR_STOP 1 ------------------------------------------------------------------ --- Test that refresh_continuous_aggregate on chunk will refresh, --- but only in the regions covered by the show chunks. ------------------------------------------------------------------ -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = 'drop_chunks_table' -ORDER BY 2,3; - chunk_name | range_start_integer | range_end_integer --------------------------+---------------------+------------------- - _dist_hyper_10_13_chunk | 0 | 10 - _dist_hyper_10_14_chunk | 10 | 20 - _dist_hyper_10_15_chunk | 20 | 30 - _dist_hyper_10_16_chunk | 30 | 40 - _dist_hyper_10_18_chunk | 40 | 50 - _dist_hyper_10_19_chunk | 50 | 60 -(6 rows) - --- Pick the second chunk as the one to drop -WITH numbered_chunks AS ( - SELECT row_number() OVER (ORDER BY range_start_integer), chunk_schema, chunk_name, range_start_integer, range_end_integer - FROM timescaledb_information.chunks - WHERE hypertable_name = 'drop_chunks_table' - ORDER BY 1 -) -SELECT format('%I.%I', chunk_schema, chunk_name) AS chunk_to_drop, range_start_integer, range_end_integer -FROM numbered_chunks -WHERE row_number = 2 \gset --- There's data in the table for the chunk/range we will drop -SELECT * FROM drop_chunks_table -WHERE time >= :range_start_integer -AND time < :range_end_integer -ORDER BY 1; - time | data -------+------ - 10 | 10 - 11 | 11 - 12 | 12 - 13 | 13 - 14 | 14 - 15 | 15 - 16 | 16 - 17 | 17 - 18 | 18 - 19 | 19 -(10 rows) - --- Make sure there is also data in the continuous aggregate --- CARE: --- Note that this behaviour of dropping the materialization table chunks and expecting a refresh --- that overlaps that time range to NOT update those chunks is undefined. Since CAGGs over --- distributed hypertables merge the invalidations the refresh region is updated in the distributed --- case, which may be different than what happens in the normal hypertable case. The command was: --- SELECT drop_chunks('drop_chunks_view', newer_than => -20, verbose => true); -CALL refresh_continuous_aggregate('drop_chunks_view', 0, 50); -SELECT * FROM drop_chunks_view -ORDER BY 1; - time_bucket | max --------------+----- - 0 | 4 - 5 | 9 - 10 | 14 - 15 | 19 - 20 | 20 - 30 | 200 - 35 | 39 - 45 | 500 - 50 | 500 -(9 rows) - --- Drop the second chunk, to leave a gap in the data -\if :IS_DISTRIBUTED -CALL distributed_exec(format('DROP TABLE IF EXISTS %s', :'chunk_to_drop')); -DROP FOREIGN TABLE :chunk_to_drop; -\else -DROP TABLE :chunk_to_drop; -\endif --- Verify that the second chunk is dropped -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = 'drop_chunks_table' -ORDER BY 2,3; - chunk_name | range_start_integer | range_end_integer --------------------------+---------------------+------------------- - _dist_hyper_10_13_chunk | 0 | 10 - _dist_hyper_10_15_chunk | 20 | 30 - _dist_hyper_10_16_chunk | 30 | 40 - _dist_hyper_10_18_chunk | 40 | 50 - _dist_hyper_10_19_chunk | 50 | 60 -(5 rows) - --- Data is no longer in the table but still in the view -SELECT * FROM drop_chunks_table -WHERE time >= :range_start_integer -AND time < :range_end_integer -ORDER BY 1; - time | data -------+------ -(0 rows) - -SELECT * FROM drop_chunks_view -WHERE time_bucket >= :range_start_integer -AND time_bucket < :range_end_integer -ORDER BY 1; - time_bucket | max --------------+----- - 10 | 14 - 15 | 19 -(2 rows) - --- Insert a large value in one of the chunks that will be dropped -INSERT INTO drop_chunks_table VALUES (:range_start_integer-1, 100); --- Now refresh and drop the two adjecent chunks -CALL refresh_continuous_aggregate('drop_chunks_view', NULL, 30); -SELECT drop_chunks('drop_chunks_table', older_than=>30); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_13_chunk - _timescaledb_internal._dist_hyper_10_15_chunk -(2 rows) - --- Verify that the chunks are dropped -SELECT chunk_name, range_start_integer, range_end_integer -FROM timescaledb_information.chunks -WHERE hypertable_name = 'drop_chunks_table' -ORDER BY 2,3; - chunk_name | range_start_integer | range_end_integer --------------------------+---------------------+------------------- - _dist_hyper_10_16_chunk | 30 | 40 - _dist_hyper_10_18_chunk | 40 | 50 - _dist_hyper_10_19_chunk | 50 | 60 -(3 rows) - --- The continuous aggregate should be refreshed in the regions covered --- by the dropped chunks, but not in the "gap" region, i.e., the --- region of the chunk that was dropped via DROP TABLE. -SELECT * FROM drop_chunks_view -ORDER BY 1; - time_bucket | max --------------+----- - 0 | 4 - 5 | 100 - 20 | 20 - 30 | 200 - 35 | 39 - 45 | 500 - 50 | 500 -(7 rows) - --- Now refresh in the region of the first two dropped chunks -CALL refresh_continuous_aggregate('drop_chunks_view', 0, :range_end_integer); --- Aggregate data in the refreshed range should no longer exist since --- the underlying data was dropped. -SELECT * FROM drop_chunks_view -ORDER BY 1; - time_bucket | max --------------+----- - 20 | 20 - 30 | 200 - 35 | 39 - 45 | 500 - 50 | 500 -(5 rows) - --------------------------------------------------------------------- --- Check that we can create a materialized table in a tablespace. We --- create one with tablespace and one without and compare them. -CREATE VIEW cagg_info AS -WITH - caggs AS ( - SELECT format('%I.%I', user_view_schema, user_view_name)::regclass AS user_view, - format('%I.%I', direct_view_schema, direct_view_name)::regclass AS direct_view, - format('%I.%I', partial_view_schema, partial_view_name)::regclass AS partial_view, - format('%I.%I', ht.schema_name, ht.table_name)::regclass AS mat_relid - FROM _timescaledb_catalog.hypertable ht, - _timescaledb_catalog.continuous_agg cagg - WHERE ht.id = cagg.mat_hypertable_id - ) -SELECT user_view, - pg_get_userbyid(relowner) AS user_view_owner, - relname AS mat_table, - (SELECT pg_get_userbyid(relowner) FROM pg_class WHERE oid = mat_relid) AS mat_table_owner, - direct_view, - (SELECT pg_get_userbyid(relowner) FROM pg_class WHERE oid = direct_view) AS direct_view_owner, - partial_view, - (SELECT pg_get_userbyid(relowner) FROM pg_class WHERE oid = partial_view) AS partial_view_owner, - (SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace - FROM pg_class JOIN caggs ON pg_class.oid = caggs.mat_relid; -GRANT SELECT ON cagg_info TO PUBLIC; -CREATE VIEW chunk_info AS -SELECT ht.schema_name, ht.table_name, relname AS chunk_name, - (SELECT spcname FROM pg_tablespace WHERE oid = reltablespace) AS tablespace - FROM pg_class c, - _timescaledb_catalog.hypertable ht, - _timescaledb_catalog.chunk ch - WHERE ch.table_name = c.relname AND ht.id = ch.hypertable_id; -CREATE TABLE whatever(time BIGINT NOT NULL, data INTEGER); -\if :IS_DISTRIBUTED -SELECT hypertable_id AS whatever_nid - FROM create_distributed_hypertable('whatever', 'time', chunk_time_interval => 10, replication_factor => 2) -\gset -psql:include/cagg_ddl_common.sql:605: WARNING: distributed hypertable is deprecated -\else -SELECT hypertable_id AS whatever_nid - FROM create_hypertable('whatever', 'time', chunk_time_interval => 10) -\gset -\endif -SELECT set_integer_now_func('whatever', 'integer_now_test'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW whatever_view_1 -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT time_bucket('5', time), COUNT(data) - FROM whatever GROUP BY 1 WITH NO DATA; -CREATE MATERIALIZED VIEW whatever_view_2 -WITH (timescaledb.continuous, timescaledb.materialized_only=true) -TABLESPACE tablespace1 AS -SELECT time_bucket('5', time), COUNT(data) - FROM whatever GROUP BY 1 WITH NO DATA; -INSERT INTO whatever SELECT i, i FROM generate_series(0, 29) AS i; -CALL refresh_continuous_aggregate('whatever_view_1', NULL, NULL); -CALL refresh_continuous_aggregate('whatever_view_2', NULL, NULL); -SELECT user_view, - mat_table, - cagg_info.tablespace AS mat_tablespace, - chunk_name, - chunk_info.tablespace AS chunk_tablespace - FROM cagg_info, chunk_info - WHERE mat_table::text = table_name - AND user_view::text LIKE 'whatever_view%'; - user_view | mat_table | mat_tablespace | chunk_name | chunk_tablespace ------------------+-----------------------------+----------------+--------------------+------------------ - whatever_view_1 | _materialized_hypertable_13 | | _hyper_13_24_chunk | - whatever_view_2 | _materialized_hypertable_14 | tablespace1 | _hyper_14_25_chunk | tablespace1 -(2 rows) - -ALTER MATERIALIZED VIEW whatever_view_1 SET TABLESPACE tablespace2; -SELECT user_view, - mat_table, - cagg_info.tablespace AS mat_tablespace, - chunk_name, - chunk_info.tablespace AS chunk_tablespace - FROM cagg_info, chunk_info - WHERE mat_table::text = table_name - AND user_view::text LIKE 'whatever_view%'; - user_view | mat_table | mat_tablespace | chunk_name | chunk_tablespace ------------------+-----------------------------+----------------+--------------------+------------------ - whatever_view_1 | _materialized_hypertable_13 | tablespace2 | _hyper_13_24_chunk | tablespace2 - whatever_view_2 | _materialized_hypertable_14 | tablespace1 | _hyper_14_25_chunk | tablespace1 -(2 rows) - -DROP MATERIALIZED VIEW whatever_view_1; -psql:include/cagg_ddl_common.sql:649: NOTICE: drop cascades to table _timescaledb_internal._hyper_13_24_chunk -DROP MATERIALIZED VIEW whatever_view_2; -psql:include/cagg_ddl_common.sql:650: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_25_chunk --- test bucket width expressions on integer hypertables -CREATE TABLE metrics_int2 ( - time int2 NOT NULL, - device_id int, - v1 float, - v2 float -); -CREATE TABLE metrics_int4 ( - time int4 NOT NULL, - device_id int, - v1 float, - v2 float -); -CREATE TABLE metrics_int8 ( - time int8 NOT NULL, - device_id int, - v1 float, - v2 float -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable (('metrics_' || dt)::regclass, 'time', chunk_time_interval => 10, replication_factor => 2) -FROM ( - VALUES ('int2'), - ('int4'), - ('int8')) v (dt); -psql:include/cagg_ddl_common.sql:679: WARNING: distributed hypertable is deprecated -psql:include/cagg_ddl_common.sql:679: WARNING: distributed hypertable is deprecated -psql:include/cagg_ddl_common.sql:679: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (15,public,metrics_int2,t) - (16,public,metrics_int4,t) - (17,public,metrics_int8,t) -(3 rows) - -\else -SELECT create_hypertable (('metrics_' || dt)::regclass, 'time', chunk_time_interval => 10) -FROM ( - VALUES ('int2'), - ('int4'), - ('int8')) v (dt); -\endif -CREATE OR REPLACE FUNCTION int2_now () - RETURNS int2 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int2 -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int2_now () - RETURNS int2 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int2 -$$; -$DIST$); -\endif -CREATE OR REPLACE FUNCTION int4_now () - RETURNS int4 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int4 -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int4_now () - RETURNS int4 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int4 -$$; -$DIST$); -\endif -CREATE OR REPLACE FUNCTION int8_now () - RETURNS int8 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int8 -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int8_now () - RETURNS int8 - LANGUAGE SQL - STABLE - AS $$ - SELECT 10::int8 -$$; -$DIST$); -\endif -SELECT set_integer_now_func (('metrics_' || dt)::regclass, (dt || '_now')::regproc) -FROM ( - VALUES ('int2'), - ('int4'), - ('int8')) v (dt); - set_integer_now_func ----------------------- - - - -(3 rows) - --- width expression for int2 hypertables -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1::smallint, time) -FROM metrics_int2 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:755: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1::smallint + 2::smallint, time) -FROM metrics_int2 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:762: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; --- width expression for int4 hypertables -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1, time) -FROM metrics_int4 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:770: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1 + 2, time) -FROM metrics_int4 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:777: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; --- width expression for int8 hypertables -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1, time) -FROM metrics_int8 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:785: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1 + 2, time) -FROM metrics_int8 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:792: NOTICE: continuous aggregate "width_expr" is already up-to-date -DROP MATERIALIZED VIEW width_expr; -\set ON_ERROR_STOP 0 --- non-immutable expresions should be rejected -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(extract(year FROM now())::smallint, time) -FROM metrics_int2 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:801: ERROR: only immutable expressions allowed in time bucket function -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(extract(year FROM now())::int, time) -FROM metrics_int4 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:806: ERROR: only immutable expressions allowed in time bucket function -CREATE MATERIALIZED VIEW width_expr WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(extract(year FROM now())::int, time) -FROM metrics_int8 -GROUP BY 1; -psql:include/cagg_ddl_common.sql:811: ERROR: only immutable expressions allowed in time bucket function -\set ON_ERROR_STOP 1 --- Test various ALTER MATERIALIZED VIEW statements. -SET ROLE :ROLE_DEFAULT_PERM_USER; -CREATE MATERIALIZED VIEW owner_check WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(1 + 2, time) -FROM metrics_int8 -GROUP BY 1 -WITH NO DATA; -\x on -SELECT * FROM cagg_info WHERE user_view::text = 'owner_check'; --[ RECORD 1 ]------+--------------------------------------- -user_view | owner_check -user_view_owner | default_perm_user -mat_table | _materialized_hypertable_24 -mat_table_owner | default_perm_user -direct_view | _timescaledb_internal._direct_view_24 -direct_view_owner | default_perm_user -partial_view | _timescaledb_internal._partial_view_24 -partial_view_owner | default_perm_user -tablespace | - -\x off --- This should not work since the target user has the wrong role, but --- we test that the normal checks are done when changing the owner. -\set ON_ERROR_STOP 0 -ALTER MATERIALIZED VIEW owner_check OWNER TO :ROLE_1; -psql:include/cagg_ddl_common.sql:831: ERROR: must be member of role "test_role_1" -\set ON_ERROR_STOP 1 --- Superuser can always change owner -SET ROLE :ROLE_CLUSTER_SUPERUSER; -ALTER MATERIALIZED VIEW owner_check OWNER TO :ROLE_1; -\x on -SELECT * FROM cagg_info WHERE user_view::text = 'owner_check'; --[ RECORD 1 ]------+--------------------------------------- -user_view | owner_check -user_view_owner | test_role_1 -mat_table | _materialized_hypertable_24 -mat_table_owner | test_role_1 -direct_view | _timescaledb_internal._direct_view_24 -direct_view_owner | test_role_1 -partial_view | _timescaledb_internal._partial_view_24 -partial_view_owner | test_role_1 -tablespace | - -\x off --- --- Test drop continuous aggregate cases --- --- Issue: #2608 --- -CREATE OR REPLACE FUNCTION test_int_now() - RETURNS INT LANGUAGE SQL STABLE AS -$BODY$ - SELECT 50; -$BODY$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ - CREATE OR REPLACE FUNCTION test_int_now() - RETURNS INT LANGUAGE SQL STABLE AS - $BODY$ - SELECT 50; - $BODY$; -$DIST$); -\endif -CREATE TABLE conditionsnm(time_int INT NOT NULL, device INT, value FLOAT); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditionsnm', 'time_int', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_ddl_common.sql:864: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (25,public,conditionsnm,t) -(1 row) - -\else -SELECT create_hypertable('conditionsnm', 'time_int', chunk_time_interval => 10); -\endif -SELECT set_integer_now_func('conditionsnm', 'test_int_now'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO conditionsnm -SELECT time_val, time_val % 4, 3.14 FROM generate_series(0,100,1) AS time_val; --- Case 1: DROP -CREATE MATERIALIZED VIEW conditionsnm_4 -WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) -AS -SELECT time_bucket(7, time_int) as bucket, -SUM(value), COUNT(value) -FROM conditionsnm GROUP BY bucket WITH DATA; -psql:include/cagg_ddl_common.sql:879: NOTICE: refreshing continuous aggregate "conditionsnm_4" -DROP materialized view conditionsnm_4; -psql:include/cagg_ddl_common.sql:881: NOTICE: drop cascades to table _timescaledb_internal._hyper_26_37_chunk --- Case 2: DROP CASCADE should have similar behaviour as DROP -CREATE MATERIALIZED VIEW conditionsnm_4 -WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) -AS -SELECT time_bucket(7, time_int) as bucket, -SUM(value), COUNT(value) -FROM conditionsnm GROUP BY bucket WITH DATA; -psql:include/cagg_ddl_common.sql:889: NOTICE: refreshing continuous aggregate "conditionsnm_4" -DROP materialized view conditionsnm_4 CASCADE; -psql:include/cagg_ddl_common.sql:891: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_38_chunk --- Case 3: require CASCADE in case of dependent object -CREATE MATERIALIZED VIEW conditionsnm_4 -WITH (timescaledb.continuous, timescaledb.materialized_only = TRUE) -AS -SELECT time_bucket(7, time_int) as bucket, -SUM(value), COUNT(value) -FROM conditionsnm GROUP BY bucket WITH DATA; -psql:include/cagg_ddl_common.sql:899: NOTICE: refreshing continuous aggregate "conditionsnm_4" -CREATE VIEW see_cagg as select * from conditionsnm_4; -\set ON_ERROR_STOP 0 -DROP MATERIALIZED VIEW conditionsnm_4; -psql:include/cagg_ddl_common.sql:903: ERROR: cannot drop view conditionsnm_4 because other objects depend on it -\set ON_ERROR_STOP 1 --- Case 4: DROP CASCADE with dependency -DROP MATERIALIZED VIEW conditionsnm_4 CASCADE; -psql:include/cagg_ddl_common.sql:907: NOTICE: drop cascades to view see_cagg -psql:include/cagg_ddl_common.sql:907: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_39_chunk --- Test DROP SCHEMA CASCADE with continuous aggregates --- --- Issue: #2350 --- --- Case 1: DROP SCHEMA CASCADE -CREATE SCHEMA test_schema; -CREATE TABLE test_schema.telemetry_raw ( - ts TIMESTAMP WITH TIME ZONE NOT NULL, - value DOUBLE PRECISION -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('test_schema.telemetry_raw', 'ts', replication_factor => 2); -psql:include/cagg_ddl_common.sql:923: WARNING: distributed hypertable is deprecated - create_distributed_hypertable ----------------------------------- - (29,test_schema,telemetry_raw,t) -(1 row) - -\else -SELECT create_hypertable('test_schema.telemetry_raw', 'ts'); -\endif -CREATE MATERIALIZED VIEW test_schema.telemetry_1s - WITH (timescaledb.continuous, timescaledb.materialized_only=false) - AS -SELECT time_bucket(INTERVAL '1s', ts) AS ts_1s, - avg(value) - FROM test_schema.telemetry_raw - GROUP BY ts_1s WITH NO DATA; -SELECT ca.raw_hypertable_id, - h.schema_name, - h.table_name AS "MAT_TABLE_NAME", - partial_view_name as "PART_VIEW_NAME", - partial_view_schema -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'telemetry_1s'; - raw_hypertable_id | schema_name | MAT_TABLE_NAME | PART_VIEW_NAME | partial_view_schema --------------------+-----------------------+-----------------------------+------------------+----------------------- - 29 | _timescaledb_internal | _materialized_hypertable_30 | _partial_view_30 | _timescaledb_internal -(1 row) - -\gset -DROP SCHEMA test_schema CASCADE; -psql:include/cagg_ddl_common.sql:946: NOTICE: drop cascades to 4 other objects -SELECT count(*) FROM pg_class WHERE relname = :'MAT_TABLE_NAME'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = :'PART_VIEW_NAME'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = 'telemetry_1s'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_namespace WHERE nspname = 'test_schema'; - count -------- - 0 -(1 row) - --- Case 2: DROP SCHEMA CASCADE with multiple caggs -CREATE SCHEMA test_schema; -CREATE TABLE test_schema.telemetry_raw ( - ts TIMESTAMP WITH TIME ZONE NOT NULL, - value DOUBLE PRECISION -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('test_schema.telemetry_raw', 'ts', replication_factor => 2); -psql:include/cagg_ddl_common.sql:962: WARNING: distributed hypertable is deprecated - create_distributed_hypertable ----------------------------------- - (31,test_schema,telemetry_raw,t) -(1 row) - -\else -SELECT create_hypertable('test_schema.telemetry_raw', 'ts'); -\endif -CREATE MATERIALIZED VIEW test_schema.cagg1 - WITH (timescaledb.continuous, timescaledb.materialized_only=false) - AS -SELECT time_bucket(INTERVAL '1s', ts) AS ts_1s, - avg(value) - FROM test_schema.telemetry_raw - GROUP BY ts_1s WITH NO DATA; -CREATE MATERIALIZED VIEW test_schema.cagg2 - WITH (timescaledb.continuous, timescaledb.materialized_only=false) - AS -SELECT time_bucket(INTERVAL '1s', ts) AS ts_1s, - avg(value) - FROM test_schema.telemetry_raw - GROUP BY ts_1s WITH NO DATA; -SELECT ca.raw_hypertable_id, - h.schema_name, - h.table_name AS "MAT_TABLE_NAME1", - partial_view_name as "PART_VIEW_NAME1", - partial_view_schema -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'cagg1'; - raw_hypertable_id | schema_name | MAT_TABLE_NAME1 | PART_VIEW_NAME1 | partial_view_schema --------------------+-----------------------+-----------------------------+------------------+----------------------- - 31 | _timescaledb_internal | _materialized_hypertable_32 | _partial_view_32 | _timescaledb_internal -(1 row) - -\gset -SELECT ca.raw_hypertable_id, - h.schema_name, - h.table_name AS "MAT_TABLE_NAME2", - partial_view_name as "PART_VIEW_NAME2", - partial_view_schema -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'cagg2'; - raw_hypertable_id | schema_name | MAT_TABLE_NAME2 | PART_VIEW_NAME2 | partial_view_schema --------------------+-----------------------+-----------------------------+------------------+----------------------- - 31 | _timescaledb_internal | _materialized_hypertable_33 | _partial_view_33 | _timescaledb_internal -(1 row) - -\gset -DROP SCHEMA test_schema CASCADE; -psql:include/cagg_ddl_common.sql:1003: NOTICE: drop cascades to 7 other objects -SELECT count(*) FROM pg_class WHERE relname = :'MAT_TABLE_NAME1'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = :'PART_VIEW_NAME1'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = 'cagg1'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = :'MAT_TABLE_NAME2'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = :'PART_VIEW_NAME2'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_class WHERE relname = 'cagg2'; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_namespace WHERE nspname = 'test_schema'; - count -------- - 0 -(1 row) - -DROP TABLESPACE tablespace1; -DROP TABLESPACE tablespace2; --- Check that we can rename a column of a materialized view and still --- rebuild it after (#3051, #3405) -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - temperature DOUBLE PRECISION NULL -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:1025: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (34,public,conditions,t) -(1 row) - -\else -SELECT create_hypertable('conditions', 'time'); -\endif -INSERT INTO conditions VALUES ( '2018-01-01 09:20:00-08', 'SFO', 55); -INSERT INTO conditions VALUES ( '2018-01-02 09:30:00-08', 'por', 100); -INSERT INTO conditions VALUES ( '2018-01-02 09:20:00-08', 'SFO', 65); -INSERT INTO conditions VALUES ( '2018-01-02 09:10:00-08', 'NYC', 65); -INSERT INTO conditions VALUES ( '2018-11-01 09:20:00-08', 'NYC', 45); -INSERT INTO conditions VALUES ( '2018-11-01 10:40:00-08', 'NYC', 55); -INSERT INTO conditions VALUES ( '2018-11-01 11:50:00-08', 'NYC', 65); -INSERT INTO conditions VALUES ( '2018-11-01 12:10:00-08', 'NYC', 75); -INSERT INTO conditions VALUES ( '2018-11-01 13:10:00-08', 'NYC', 85); -INSERT INTO conditions VALUES ( '2018-11-02 09:20:00-08', 'NYC', 10); -INSERT INTO conditions VALUES ( '2018-11-02 10:30:00-08', 'NYC', 20); -CREATE MATERIALIZED VIEW conditions_daily -WITH (timescaledb.continuous, timescaledb.materialized_only = false) AS -SELECT location, - time_bucket(INTERVAL '1 day', time) AS bucket, - AVG(temperature) - FROM conditions -GROUP BY location, bucket -WITH NO DATA; -SELECT format('%I.%I', '_timescaledb_internal', h.table_name) AS "MAT_TABLE_NAME", - format('%I.%I', '_timescaledb_internal', partial_view_name) AS "PART_VIEW_NAME", - format('%I.%I', '_timescaledb_internal', direct_view_name) AS "DIRECT_VIEW_NAME" -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'conditions_daily' -\gset --- Show both the columns and the view definitions to see that --- references are correct in the view as well. -SELECT * FROM test.show_columns('conditions_daily'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - bucket | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'DIRECT_VIEW_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - bucket | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'PART_VIEW_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - bucket | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'MAT_TABLE_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - bucket | timestamp with time zone | t - avg | double precision | f -(3 rows) - -ALTER MATERIALIZED VIEW conditions_daily RENAME COLUMN bucket to "time"; --- Show both the columns and the view definitions to see that --- references are correct in the view as well. -SELECT * FROM test.show_columns(' conditions_daily'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - time | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'DIRECT_VIEW_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - time | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'PART_VIEW_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - time | timestamp with time zone | f - avg | double precision | f -(3 rows) - -SELECT * FROM test.show_columns(:'MAT_TABLE_NAME'); - Column | Type | NotNull -----------+--------------------------+--------- - location | text | f - time | timestamp with time zone | t - avg | double precision | f -(3 rows) - --- This will rebuild the materialized view and should succeed. -ALTER MATERIALIZED VIEW conditions_daily SET (timescaledb.materialized_only = false); --- Refresh the continuous aggregate to check that it works after the --- rename. -\set VERBOSITY verbose -CALL refresh_continuous_aggregate('conditions_daily', NULL, NULL); -\set VERBOSITY terse --- --- Indexes on continuous aggregate --- -\set ON_ERROR_STOP 0 --- unique indexes are not supported -CREATE UNIQUE INDEX index_unique_error ON conditions_daily ("time", location); -psql:include/cagg_ddl_common.sql:1089: ERROR: continuous aggregates do not support UNIQUE indexes --- concurrently index creation not supported -CREATE INDEX CONCURRENTLY index_concurrently_avg ON conditions_daily (avg); -psql:include/cagg_ddl_common.sql:1091: ERROR: hypertables do not support concurrent index creation -\set ON_ERROR_STOP 1 -CREATE INDEX index_avg ON conditions_daily (avg); -CREATE INDEX index_avg_only ON ONLY conditions_daily (avg); -CREATE INDEX index_avg_include ON conditions_daily (avg) INCLUDE (location); -CREATE INDEX index_avg_expr ON conditions_daily ((avg + 1)); -CREATE INDEX index_avg_location_sfo ON conditions_daily (avg) WHERE location = 'SFO'; -CREATE INDEX index_avg_expr_location_sfo ON conditions_daily ((avg + 2)) WHERE location = 'SFO'; -SELECT * FROM test.show_indexespred(:'MAT_TABLE_NAME'); - Index | Columns | Expr | Pred | Unique | Primary | Exclusion | Tablespace ------------------------------------------------------------------------+-------------------+---------------------------+------------------------+--------+---------+-----------+------------ - _timescaledb_internal._materialized_hypertable_35_bucket_idx | {bucket} | | | f | f | f | - _timescaledb_internal._materialized_hypertable_35_location_bucket_idx | {location,bucket} | | | f | f | f | - _timescaledb_internal.index_avg | {avg} | | | f | f | f | - _timescaledb_internal.index_avg_expr | {expr} | avg + 1::double precision | | f | f | f | - _timescaledb_internal.index_avg_expr_location_sfo | {expr} | avg + 2::double precision | location = 'SFO'::text | f | f | f | - _timescaledb_internal.index_avg_include | {avg,location} | | | f | f | f | - _timescaledb_internal.index_avg_location_sfo | {avg} | | location = 'SFO'::text | f | f | f | - _timescaledb_internal.index_avg_only | {avg} | | | f | f | f | -(8 rows) - --- #3696 assertion failure when referencing columns not present in result -CREATE TABLE i3696(time timestamptz NOT NULL, search_query text, cnt integer, cnt2 integer); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('i3696', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:1105: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (36,public,i3696,t) -(1 row) - -\else -SELECT table_name FROM create_hypertable('i3696','time'); -\endif -CREATE MATERIALIZED VIEW i3696_cagg1 WITH (timescaledb.continuous, timescaledb.materialized_only=false) -AS - SELECT search_query,count(search_query) as count, sum(cnt), time_bucket(INTERVAL '1 minute', time) AS bucket - FROM i3696 GROUP BY cnt +cnt2 , bucket, search_query; -psql:include/cagg_ddl_common.sql:1113: NOTICE: continuous aggregate "i3696_cagg1" is already up-to-date -ALTER MATERIALIZED VIEW i3696_cagg1 SET (timescaledb.materialized_only = 'true'); -CREATE MATERIALIZED VIEW i3696_cagg2 WITH (timescaledb.continuous, timescaledb.materialized_only=false) -AS - SELECT search_query,count(search_query) as count, sum(cnt), time_bucket(INTERVAL '1 minute', time) AS bucket - FROM i3696 GROUP BY cnt + cnt2, bucket, search_query - HAVING cnt + cnt2 + sum(cnt) > 2 or count(cnt2) > 10; -psql:include/cagg_ddl_common.sql:1121: NOTICE: continuous aggregate "i3696_cagg2" is already up-to-date -ALTER MATERIALIZED VIEW i3696_cagg2 SET (timescaledb.materialized_only = 'true'); ---TEST test with multiple settings on continuous aggregates -- --- test for materialized_only + compress combinations (real time aggs enabled initially) -CREATE TABLE test_setting(time timestamptz not null, val numeric); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('test_setting', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:1129: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (39,public,test_setting,t) -(1 row) - -\else -SELECT create_hypertable('test_setting', 'time'); -\endif -CREATE MATERIALIZED VIEW test_setting_cagg with (timescaledb.continuous, timescaledb.materialized_only=false) -AS SELECT time_bucket('1h',time), avg(val), count(*) FROM test_setting GROUP BY 1; -psql:include/cagg_ddl_common.sql:1135: NOTICE: continuous aggregate "test_setting_cagg" is already up-to-date -INSERT INTO test_setting -SELECT generate_series( '2020-01-10 8:00'::timestamp, '2020-01-30 10:00+00'::timestamptz, '1 day'::interval), 10.0; -CALL refresh_continuous_aggregate('test_setting_cagg', NULL, '2020-05-30 10:00+00'::timestamptz); -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - ---this row is not in the materialized result --- -INSERT INTO test_setting VALUES( '2020-11-01', 20); ---try out 2 settings here -- -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'true', timescaledb.compress='true'); -psql:include/cagg_ddl_common.sql:1146: NOTICE: defaulting compress_orderby to time_bucket -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | t | t -(1 row) - ---real time aggs is off now , should return 20 -- -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - ---now set it back to false -- -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'false', timescaledb.compress='true'); -psql:include/cagg_ddl_common.sql:1154: NOTICE: defaulting compress_orderby to time_bucket -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | t | f -(1 row) - ---count should return additional data since we have real time aggs on -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 21 -(1 row) - -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'true', timescaledb.compress='false'); -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | f | t -(1 row) - ---real time aggs is off now , should return 20 -- -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'false', timescaledb.compress='false'); -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | f | f -(1 row) - ---count should return additional data since we have real time aggs on -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 21 -(1 row) - -DELETE FROM test_setting WHERE val = 20; ---TEST test with multiple settings on continuous aggregates with real time aggregates turned off initially -- --- test for materialized_only + compress combinations (real time aggs enabled initially) -DROP MATERIALIZED VIEW test_setting_cagg; -psql:include/cagg_ddl_common.sql:1179: NOTICE: drop cascades to table _timescaledb_internal._hyper_40_47_chunk -CREATE MATERIALIZED VIEW test_setting_cagg with (timescaledb.continuous, timescaledb.materialized_only = true) -AS SELECT time_bucket('1h',time), avg(val), count(*) FROM test_setting GROUP BY 1; -psql:include/cagg_ddl_common.sql:1182: NOTICE: refreshing continuous aggregate "test_setting_cagg" -CALL refresh_continuous_aggregate('test_setting_cagg', NULL, '2020-05-30 10:00+00'::timestamptz); -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - ---this row is not in the materialized result --- -INSERT INTO test_setting VALUES( '2020-11-01', 20); ---try out 2 settings here -- -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'false', timescaledb.compress='true'); -psql:include/cagg_ddl_common.sql:1190: NOTICE: defaulting compress_orderby to time_bucket -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | t | f -(1 row) - ---count should return additional data since we have real time aggs on -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 21 -(1 row) - ---now set it back to false -- -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'true', timescaledb.compress='true'); -psql:include/cagg_ddl_common.sql:1198: NOTICE: defaulting compress_orderby to time_bucket -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | t | t -(1 row) - ---real time aggs is off now , should return 20 -- -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'false', timescaledb.compress='false'); -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | f | f -(1 row) - ---count should return additional data since we have real time aggs on -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 21 -(1 row) - -ALTER MATERIALIZED VIEW test_setting_cagg SET (timescaledb.materialized_only = 'true', timescaledb.compress='false'); -SELECT view_name, compression_enabled, materialized_only -FROM timescaledb_information.continuous_aggregates -where view_name = 'test_setting_cagg'; - view_name | compression_enabled | materialized_only --------------------+---------------------+------------------- - test_setting_cagg | f | t -(1 row) - ---real time aggs is off now , should return 20 -- -SELECT count(*) from test_setting_cagg ORDER BY 1; - count -------- - 20 -(1 row) - --- END TEST with multiple settings --- Test View Target Entries that contain both aggrefs and Vars in the same expression -CREATE TABLE transactions -( - "time" timestamp with time zone NOT NULL, - dummy1 integer, - dummy2 integer, - dummy3 integer, - dummy4 integer, - dummy5 integer, - amount integer, - fiat_value integer -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('transactions', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:1235: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (46,public,transactions,t) -(1 row) - -\else -SELECT create_hypertable('transactions', 'time'); -\endif -INSERT INTO transactions VALUES ( '2018-01-01 09:20:00-08', 0, 0, 0, 0, 0, 1, 10); -INSERT INTO transactions VALUES ( '2018-01-02 09:30:00-08', 0, 0, 0, 0, 0, -1, 10); -INSERT INTO transactions VALUES ( '2018-01-02 09:20:00-08', 0, 0, 0, 0, 0, -1, 10); -INSERT INTO transactions VALUES ( '2018-01-02 09:10:00-08', 0, 0, 0, 0, 0, -1, 10); -INSERT INTO transactions VALUES ( '2018-11-01 09:20:00-08', 0, 0, 0, 0, 0, 1, 10); -INSERT INTO transactions VALUES ( '2018-11-01 10:40:00-08', 0, 0, 0, 0, 0, 1, 10); -INSERT INTO transactions VALUES ( '2018-11-01 11:50:00-08', 0, 0, 0, 0, 0, 1, 10); -INSERT INTO transactions VALUES ( '2018-11-01 12:10:00-08', 0, 0, 0, 0, 0, -1, 10); -INSERT INTO transactions VALUES ( '2018-11-01 13:10:00-08', 0, 0, 0, 0, 0, -1, 10); -INSERT INTO transactions VALUES ( '2018-11-02 09:20:00-08', 0, 0, 0, 0, 0, 1, 10); -INSERT INTO transactions VALUES ( '2018-11-02 10:30:00-08', 0, 0, 0, 0, 0, -1, 10); -CREATE materialized view cashflows( - bucket, - amount, - cashflow, - cashflow2 -) WITH ( - timescaledb.continuous, - timescaledb.materialized_only = true -) AS -SELECT time_bucket ('1 day', time) AS bucket, - amount, - CASE - WHEN amount < 0 THEN (0 - sum(fiat_value)) - ELSE sum(fiat_value) - END AS cashflow, - amount + sum(fiat_value) -FROM transactions -GROUP BY bucket, amount; -psql:include/cagg_ddl_common.sql:1272: NOTICE: refreshing continuous aggregate "cashflows" -SELECT h.table_name AS "MAT_TABLE_NAME", - partial_view_name AS "PART_VIEW_NAME", - direct_view_name AS "DIRECT_VIEW_NAME" -FROM _timescaledb_catalog.continuous_agg ca -INNER JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE user_view_name = 'cashflows' -\gset --- Show both the columns and the view definitions to see that --- references are correct in the view as well. -\d+ "_timescaledb_internal".:"DIRECT_VIEW_NAME" - View "_timescaledb_internal._direct_view_47" - Column | Type | Collation | Nullable | Default | Storage | Description ------------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - amount | integer | | | | plain | - cashflow | bigint | | | | plain | - cashflow2 | bigint | | | | plain | -View definition: - SELECT time_bucket('@ 1 day'::interval, transactions."time") AS bucket, - transactions.amount, - CASE - WHEN transactions.amount < 0 THEN 0 - sum(transactions.fiat_value) - ELSE sum(transactions.fiat_value) - END AS cashflow, - transactions.amount + sum(transactions.fiat_value) AS cashflow2 - FROM transactions - GROUP BY (time_bucket('@ 1 day'::interval, transactions."time")), transactions.amount; - -\d+ "_timescaledb_internal".:"PART_VIEW_NAME" - View "_timescaledb_internal._partial_view_47" - Column | Type | Collation | Nullable | Default | Storage | Description ------------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - amount | integer | | | | plain | - cashflow | bigint | | | | plain | - cashflow2 | bigint | | | | plain | -View definition: - SELECT time_bucket('@ 1 day'::interval, transactions."time") AS bucket, - transactions.amount, - CASE - WHEN transactions.amount < 0 THEN 0 - sum(transactions.fiat_value) - ELSE sum(transactions.fiat_value) - END AS cashflow, - transactions.amount + sum(transactions.fiat_value) AS cashflow2 - FROM transactions - GROUP BY (time_bucket('@ 1 day'::interval, transactions."time")), transactions.amount; - -\d+ "_timescaledb_internal".:"MAT_TABLE_NAME" - Table "_timescaledb_internal._materialized_hypertable_47" - Column | Type | Collation | Nullable | Default | Storage | Stats target | Description ------------+--------------------------+-----------+----------+---------+---------+--------------+------------- - bucket | timestamp with time zone | | not null | | plain | | - amount | integer | | | | plain | | - cashflow | bigint | | | | plain | | - cashflow2 | bigint | | | | plain | | -Indexes: - "_materialized_hypertable_47_amount_bucket_idx" btree (amount, bucket DESC) - "_materialized_hypertable_47_bucket_idx" btree (bucket DESC) -Triggers: - ts_insert_blocker BEFORE INSERT ON _timescaledb_internal._materialized_hypertable_47 FOR EACH ROW EXECUTE FUNCTION _timescaledb_functions.insert_blocker() -Child tables: _timescaledb_internal._hyper_47_52_chunk, - _timescaledb_internal._hyper_47_53_chunk - -\d+ 'cashflows' - View "public.cashflows" - Column | Type | Collation | Nullable | Default | Storage | Description ------------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - amount | integer | | | | plain | - cashflow | bigint | | | | plain | - cashflow2 | bigint | | | | plain | -View definition: - SELECT _materialized_hypertable_47.bucket, - _materialized_hypertable_47.amount, - _materialized_hypertable_47.cashflow, - _materialized_hypertable_47.cashflow2 - FROM _timescaledb_internal._materialized_hypertable_47; - -SELECT * FROM cashflows; - bucket | amount | cashflow | cashflow2 -------------------------------+--------+----------+----------- - Sun Dec 31 16:00:00 2017 PST | 1 | 10 | 11 - Mon Jan 01 16:00:00 2018 PST | -1 | -30 | 29 - Wed Oct 31 17:00:00 2018 PDT | -1 | -20 | 19 - Wed Oct 31 17:00:00 2018 PDT | 1 | 30 | 31 - Thu Nov 01 17:00:00 2018 PDT | -1 | -10 | 9 - Thu Nov 01 17:00:00 2018 PDT | 1 | 10 | 11 -(6 rows) - --- test cagg creation with named arguments in time_bucket --- note that positional arguments cannot follow named arguments --- 1. test named origin --- 2. test named timezone --- 3. test named ts --- 4. test named bucket width --- named origin -CREATE MATERIALIZED VIEW cagg_named_origin WITH -(timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket('1h', time, 'UTC', origin => '2001-01-03 01:23:45') AS bucket, -avg(amount) as avg_amount -FROM transactions GROUP BY 1 WITH NO DATA; --- named timezone -CREATE MATERIALIZED VIEW cagg_named_tz_origin WITH -(timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket('1h', time, timezone => 'UTC', origin => '2001-01-03 01:23:45') AS bucket, -avg(amount) as avg_amount -FROM transactions GROUP BY 1 WITH NO DATA; --- named ts -CREATE MATERIALIZED VIEW cagg_named_ts_tz_origin WITH -(timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket('1h', ts => time, timezone => 'UTC', origin => '2001-01-03 01:23:45') AS bucket, -avg(amount) as avg_amount -FROM transactions GROUP BY 1 WITH NO DATA; --- named bucket width -CREATE MATERIALIZED VIEW cagg_named_all WITH -(timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(bucket_width => '1h', ts => time, timezone => 'UTC', origin => '2001-01-03 01:23:45') AS bucket, -avg(amount) as avg_amount -FROM transactions GROUP BY 1 WITH NO DATA; --- Refreshing from the beginning (NULL) of a CAGG with variable time bucket and --- using an INTERVAL for the end timestamp (issue #5534) -CREATE MATERIALIZED VIEW transactions_montly -WITH (timescaledb.continuous, timescaledb.materialized_only = true) AS -SELECT time_bucket(INTERVAL '1 month', time) AS bucket, - SUM(fiat_value), - MAX(fiat_value), - MIN(fiat_value) - FROM transactions -GROUP BY 1 -WITH NO DATA; --- No rows -SELECT * FROM transactions_montly ORDER BY bucket; - bucket | sum | max | min ---------+-----+-----+----- -(0 rows) - --- Refresh from beginning of the CAGG for 1 month -CALL refresh_continuous_aggregate('transactions_montly', NULL, INTERVAL '1 month'); -SELECT * FROM transactions_montly ORDER BY bucket; - bucket | sum | max | min -------------------------------+-----+-----+----- - Sun Dec 31 16:00:00 2017 PST | 40 | 10 | 10 - Wed Oct 31 17:00:00 2018 PDT | 70 | 10 | 10 -(2 rows) - -TRUNCATE transactions_montly; --- Partial refresh the CAGG from beginning to an specific timestamp -CALL refresh_continuous_aggregate('transactions_montly', NULL, '2018-11-01 11:50:00-08'::timestamptz); -SELECT * FROM transactions_montly ORDER BY bucket; - bucket | sum | max | min -------------------------------+-----+-----+----- - Sun Dec 31 16:00:00 2017 PST | 40 | 10 | 10 -(1 row) - --- Full refresh the CAGG -CALL refresh_continuous_aggregate('transactions_montly', NULL, NULL); -SELECT * FROM transactions_montly ORDER BY bucket; - bucket | sum | max | min -------------------------------+-----+-----+----- - Sun Dec 31 16:00:00 2017 PST | 40 | 10 | 10 - Wed Oct 31 17:00:00 2018 PDT | 70 | 10 | 10 -(2 rows) - --- Check set_chunk_time_interval on continuous aggregate -CREATE MATERIALIZED VIEW cagg_set_chunk_time_interval -WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT time_bucket(INTERVAL '1 month', time) AS bucket, - SUM(fiat_value), - MAX(fiat_value), - MIN(fiat_value) -FROM transactions -GROUP BY 1 -WITH NO DATA; -SELECT set_chunk_time_interval('cagg_set_chunk_time_interval', chunk_time_interval => interval '1 month'); - set_chunk_time_interval -------------------------- - -(1 row) - -CALL refresh_continuous_aggregate('cagg_set_chunk_time_interval', NULL, NULL); -SELECT _timescaledb_functions.to_interval(d.interval_length) = interval '1 month' -FROM _timescaledb_catalog.dimension d - RIGHT JOIN _timescaledb_catalog.continuous_agg ca ON ca.user_view_name = 'cagg_set_chunk_time_interval' -WHERE d.hypertable_id = ca.mat_hypertable_id; - ?column? ----------- - t -(1 row) - --- Since #6077 CAggs are materialized only by default -DROP TABLE conditions CASCADE; -psql:include/cagg_ddl_common.sql:1370: NOTICE: drop cascades to 3 other objects -psql:include/cagg_ddl_common.sql:1370: NOTICE: drop cascades to 2 other objects -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - temperature DOUBLE PRECISION NULL -); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_ddl_common.sql:1378: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (54,public,conditions,t) -(1 row) - -\else -SELECT create_hypertable('conditions', 'time'); -\endif -INSERT INTO conditions VALUES ( '2018-01-01 09:20:00-08', 'SFO', 55); -INSERT INTO conditions VALUES ( '2018-01-02 09:30:00-08', 'por', 100); -INSERT INTO conditions VALUES ( '2018-01-02 09:20:00-08', 'SFO', 65); -INSERT INTO conditions VALUES ( '2018-01-02 09:10:00-08', 'NYC', 65); -INSERT INTO conditions VALUES ( '2018-11-01 09:20:00-08', 'NYC', 45); -INSERT INTO conditions VALUES ( '2018-11-01 10:40:00-08', 'NYC', 55); -INSERT INTO conditions VALUES ( '2018-11-01 11:50:00-08', 'NYC', 65); -INSERT INTO conditions VALUES ( '2018-11-01 12:10:00-08', 'NYC', 75); -INSERT INTO conditions VALUES ( '2018-11-01 13:10:00-08', 'NYC', 85); -INSERT INTO conditions VALUES ( '2018-11-02 09:20:00-08', 'NYC', 10); -INSERT INTO conditions VALUES ( '2018-11-02 10:30:00-08', 'NYC', 20); -CREATE MATERIALIZED VIEW conditions_daily -WITH (timescaledb.continuous) AS -SELECT location, - time_bucket(INTERVAL '1 day', time) AS bucket, - AVG(temperature) - FROM conditions -GROUP BY location, bucket -WITH NO DATA; -\d+ conditions_daily - View "public.conditions_daily" - Column | Type | Collation | Nullable | Default | Storage | Description -----------+--------------------------+-----------+----------+---------+----------+------------- - location | text | | | | extended | - bucket | timestamp with time zone | | | | plain | - avg | double precision | | | | plain | -View definition: - SELECT _materialized_hypertable_55.location, - _materialized_hypertable_55.bucket, - _materialized_hypertable_55.avg - FROM _timescaledb_internal._materialized_hypertable_55; - --- Should return NO ROWS -SELECT * FROM conditions_daily ORDER BY bucket, avg; - location | bucket | avg -----------+--------+----- -(0 rows) - -ALTER MATERIALIZED VIEW conditions_daily SET (timescaledb.materialized_only=false); -\d+ conditions_daily - View "public.conditions_daily" - Column | Type | Collation | Nullable | Default | Storage | Description -----------+--------------------------+-----------+----------+---------+----------+------------- - location | text | | | | extended | - bucket | timestamp with time zone | | | | plain | - avg | double precision | | | | plain | -View definition: - SELECT _materialized_hypertable_55.location, - _materialized_hypertable_55.bucket, - _materialized_hypertable_55.avg - 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 conditions.location, - time_bucket('@ 1 day'::interval, conditions."time") AS bucket, - avg(conditions.temperature) AS avg - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(55)), '-infinity'::timestamp with time zone) - GROUP BY conditions.location, (time_bucket('@ 1 day'::interval, conditions."time")); - --- Should return ROWS because now it is realtime -SELECT * FROM conditions_daily ORDER BY bucket, avg; - location | bucket | avg -----------+------------------------------+----- - SFO | Sun Dec 31 16:00:00 2017 PST | 55 - NYC | Mon Jan 01 16:00:00 2018 PST | 65 - SFO | Mon Jan 01 16:00:00 2018 PST | 65 - por | Mon Jan 01 16:00:00 2018 PST | 100 - NYC | Wed Oct 31 17:00:00 2018 PDT | 65 - NYC | Thu Nov 01 17:00:00 2018 PDT | 15 -(6 rows) - --- Should return ROWS because we refreshed it -ALTER MATERIALIZED VIEW conditions_daily SET (timescaledb.materialized_only=true); -\d+ conditions_daily - View "public.conditions_daily" - Column | Type | Collation | Nullable | Default | Storage | Description -----------+--------------------------+-----------+----------+---------+----------+------------- - location | text | | | | extended | - bucket | timestamp with time zone | | | | plain | - avg | double precision | | | | plain | -View definition: - SELECT _materialized_hypertable_55.location, - _materialized_hypertable_55.bucket, - _materialized_hypertable_55.avg - FROM _timescaledb_internal._materialized_hypertable_55; - -CALL refresh_continuous_aggregate('conditions_daily', NULL, NULL); -SELECT * FROM conditions_daily ORDER BY bucket, avg; - location | bucket | avg -----------+------------------------------+----- - SFO | Sun Dec 31 16:00:00 2017 PST | 55 - SFO | Mon Jan 01 16:00:00 2018 PST | 65 - NYC | Mon Jan 01 16:00:00 2018 PST | 65 - por | Mon Jan 01 16:00:00 2018 PST | 100 - NYC | Wed Oct 31 17:00:00 2018 PDT | 65 - NYC | Thu Nov 01 17:00:00 2018 PDT | 15 -(6 rows) - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_invalidation_dist_ht-13.out b/tsl/test/expected/cagg_invalidation_dist_ht-13.out deleted file mode 100644 index f250cb23a80..00000000000 --- a/tsl/test/expected/cagg_invalidation_dist_ht-13.out +++ /dev/null @@ -1,2207 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------------+--------------------------------+--------------+------------------+------------------- - db_cagg_invalidation_dist_ht_1 | db_cagg_invalidation_dist_ht_1 | t | t | t - db_cagg_invalidation_dist_ht_2 | db_cagg_invalidation_dist_ht_2 | t | t | t - db_cagg_invalidation_dist_ht_3 | db_cagg_invalidation_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER, :ROLE_DEFAULT_PERM_USER_2; -\set IS_DISTRIBUTED TRUE -\ir include/cagg_invalidation_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. --- Disable background workers since we are testing manual refresh -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT _timescaledb_functions.stop_background_workers(); - stop_background_workers -------------------------- - t -(1 row) - -SET ROLE :ROLE_DEFAULT_PERM_USER; -SET datestyle TO 'ISO, YMD'; -SET timezone TO 'UTC'; -CREATE TABLE conditions (time bigint NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:14: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,conditions,t) -(1 row) - -\else -SELECT create_hypertable('conditions', 'time', chunk_time_interval => 10); -\endif -CREATE TABLE measurements (time int NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('measurements', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:21: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,measurements,t) -(1 row) - -\else -SELECT create_hypertable('measurements', 'time', chunk_time_interval => 10); -\endif -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -$DIST$); -\endif -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -$DIST$); -\endif -SELECT set_integer_now_func('conditions', 'bigint_now'); - set_integer_now_func ----------------------- - -(1 row) - -SELECT set_integer_now_func('measurements', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO conditions -SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::int, - abs(timestamp_hash(to_timestamp(t)::timestamp))%40 -FROM generate_series(1, 100, 1) t; -CREATE TABLE temp AS -SELECT * FROM conditions; -INSERT INTO measurements -SELECT * FROM temp; --- Show the most recent data -SELECT * FROM conditions -ORDER BY time DESC, device -LIMIT 10; - time | device | temp -------+--------+------ - 100 | 0 | 8 - 99 | 1 | 5 - 98 | 2 | 26 - 97 | 2 | 10 - 96 | 2 | 34 - 95 | 2 | 30 - 94 | 3 | 31 - 93 | 0 | 4 - 92 | 0 | 32 - 91 | 3 | 15 -(10 rows) - --- Create two continuous aggregates on the same hypertable to test --- that invalidations are handled correctly across both of them. -CREATE MATERIALIZED VIEW cond_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '10', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW cond_20 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '20', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW measure_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(10, time) AS bucket, device, avg(temp) AS avg_temp -FROM measurements -GROUP BY 1,2 WITH NO DATA; --- There should be three continuous aggregates, two on one hypertable --- and one on the other: -SELECT mat_hypertable_id, raw_hypertable_id, user_view_name -FROM _timescaledb_catalog.continuous_agg; - mat_hypertable_id | raw_hypertable_id | user_view_name --------------------+-------------------+---------------- - 3 | 1 | cond_10 - 4 | 1 | cond_20 - 5 | 2 | measure_10 -(3 rows) - --- The continuous aggregates should be empty -SELECT * FROM cond_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM measure_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -\if :IS_DISTRIBUTED -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT materialization_id AS cagg_id, - lowest_modified_value AS start, - greatest_modified_value AS end - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -\else -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE ( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log - ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE ( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT materialization_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log - ORDER BY 1,2,3 -$$; -\endif -CREATE VIEW hyper_invals AS SELECT * FROM get_hyper_invals(); -CREATE VIEW cagg_invals AS SELECT * FROM get_cagg_invals(); --- Must refresh to move the invalidation threshold, or no --- invalidations will be generated. Initially, threshold is the --- MIN of the time dimension data type: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+---------------------- - 1 | -9223372036854775808 - 2 | -2147483648 -(2 rows) - --- There should be only "infinite" invalidations in the cagg --- invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(3 rows) - --- Now refresh up to 50 without the first bucket, and the threshold should be updated accordingly: -CALL refresh_continuous_aggregate('cond_10', 1, 50); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Invalidations should be cleared inside the refresh window: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refresh up to 50 from the beginning -CALL refresh_continuous_aggregate('cond_10', 0, 50); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing below the threshold does not move it: -CALL refresh_continuous_aggregate('cond_10', 20, 49); -psql:include/cagg_invalidation_common.sql:207: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Nothing changes with invalidations either since the region was --- already refreshed and no new invalidations have been generated: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing measure_10 moves the threshold only for the other hypertable: -CALL refresh_continuous_aggregate('measure_10', 0, 30); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 50 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(5 rows) - --- Refresh on the second continuous aggregate, cond_20, on the first --- hypertable moves the same threshold as when refreshing cond_10: -CALL refresh_continuous_aggregate('cond_20', 60, 100); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- There should be no hypertable invalidations initially: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:229: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- -(0 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Create invalidations across different ranges. Some of these should --- be deleted and others cut in different ways when a refresh is --- run. Note that the refresh window is inclusive in the start of the --- window but exclusive at the end. --- Entries that should be left unmodified: -INSERT INTO conditions VALUES (10, 4, 23.7); -INSERT INTO conditions VALUES (10, 5, 23.8), (19, 3, 23.6); -INSERT INTO conditions VALUES (60, 3, 23.7), (70, 4, 23.7); --- Should see some invaliations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 -(5 rows) - --- Generate some invalidations for the other hypertable -INSERT INTO measurements VALUES (20, 4, 23.7); -INSERT INTO measurements VALUES (30, 5, 23.8), (80, 3, 23.6); --- Should now see invalidations for both hypertables -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 - 2 | 20 | 20 - 2 | 30 | 80 -(7 rows) - --- First refresh a window where we don't have any invalidations. This --- allows us to see only the copying of the invalidations to the per --- cagg log without additional processing. -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidation threshold remains at 100: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log, but only for the hypertable that --- the refreshed aggregate belongs to: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Now add more invalidations to test a refresh that overlaps with them. --- Entries that should be deleted: -INSERT INTO conditions VALUES (30, 1, 23.4), (59, 1, 23.4); -INSERT INTO conditions VALUES (20, 1, 23.4), (30, 1, 23.4); --- Entries that should be cut to the right, leaving an invalidation to --- the left of the refresh window: -INSERT INTO conditions VALUES (1, 4, 23.7), (25, 1, 23.4); -INSERT INTO conditions VALUES (19, 4, 23.7), (59, 1, 23.4); --- Entries that should be cut to the left and right, leaving two --- invalidation entries on each side of the refresh window: -INSERT INTO conditions VALUES (2, 2, 23.5), (60, 1, 23.4); -INSERT INTO conditions VALUES (3, 2, 23.5), (80, 1, 23.4); --- Entries that should be cut to the left, leaving an invalidation to --- the right of the refresh window: -INSERT INTO conditions VALUES (60, 3, 23.6), (90, 3, 23.6); -INSERT INTO conditions VALUES (20, 5, 23.8), (100, 3, 23.6); --- New invalidations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 1 | 1 - 1 | 1 | 25 - 1 | 2 | 60 - 1 | 3 | 3 - 1 | 3 | 80 - 1 | 19 | 19 - 1 | 19 | 59 - 1 | 20 | 20 - 1 | 20 | 30 - 1 | 20 | 100 - 1 | 25 | 25 - 1 | 30 | 30 - 1 | 30 | 59 - 1 | 59 | 59 - 1 | 60 | 90 - 1 | 80 | 80 - 1 | 100 | 100 - 2 | 20 | 20 - 2 | 30 | 80 -(19 rows) - --- But nothing has yet changed in the cagg invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh to process invalidations for daily temperature: -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log. -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Only the cond_10 cagg should have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 0 | 99 - 4 | 0 | 119 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(12 rows) - --- Refresh also cond_20: -CALL refresh_continuous_aggregate('cond_20', 20, 60); --- The cond_20 cagg should also have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - --- Refresh cond_10 to completely remove an invalidation: -CALL refresh_continuous_aggregate('cond_10', 0, 20); --- The 1-19 invalidation should be deleted: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Clear everything between 0 and 100 to make way for new --- invalidations -CALL refresh_continuous_aggregate('cond_10', 0, 100); --- Test refreshing with non-overlapping invalidations -INSERT INTO conditions VALUES (20, 1, 23.4), (25, 1, 23.4); -INSERT INTO conditions VALUES (30, 1, 23.4), (46, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 1, 40); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 40 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh whithout cutting (in area where there are no --- invalidations). Merging of overlapping entries should still happen: -INSERT INTO conditions VALUES (15, 1, 23.4), (42, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 90, 100); -psql:include/cagg_invalidation_common.sql:327: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(10 rows) - --- Test max refresh window -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | 110 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Pick the first chunk of conditions to TRUNCATE -SELECT show_chunks AS chunk_to_truncate -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before truncating one of the chunks -SELECT * FROM :chunk_to_truncate -ORDER BY 1; - time | device | temp -------+--------+------ - 1 | 4 | 23.7 - 1 | 0 | 16 - 2 | 2 | 23.5 - 2 | 1 | 25 - 3 | 2 | 23.5 - 3 | 0 | 20 - 4 | 2 | 10 - 5 | 2 | 26 - 6 | 1 | 13 - 7 | 3 | 35 - 8 | 1 | 37 - 9 | 3 | 7 -(12 rows) - --- Truncate one chunk -\if :IS_DISTRIBUTED --- There is no TRUNCATE implementation for FOREIGN tables yet -\set ON_ERROR_STOP 0 -\endif -TRUNCATE TABLE :chunk_to_truncate; -psql:include/cagg_invalidation_common.sql:352: ERROR: "_dist_hyper_1_1_chunk" is not a table -\if :IS_DISTRIBUTED -\set ON_ERROR_STOP 1 -\endif --- Should see new invalidation entries for conditions for the non-distributed case -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- TRUNCATE the hypertable to invalidate all its continuous aggregates -TRUNCATE conditions; --- Now empty -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - --- Should see an infinite invalidation entry for conditions -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+----------------------+--------------------- - 1 | -9223372036854775808 | 9223372036854775807 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Aggregates still hold data -SELECT * FROM cond_10 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+---------- - 0 | 0 | 18 - 0 | 1 | 25 - 0 | 2 | 20.75 - 0 | 3 | 21 - 0 | 4 | 23.7 -(5 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+------------------ - 20 | 0 | 18.2857142857143 - 20 | 1 | 23.5142857142857 - 20 | 2 | 26 - 20 | 3 | 23 - 20 | 5 | 23.8 -(5 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Both should now be empty after refresh -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Insert new data again and refresh -INSERT INTO conditions VALUES - (1, 1, 23.4), (4, 3, 14.3), (5, 1, 13.6), - (6, 2, 17.9), (12, 1, 18.3), (19, 3, 28.2), - (10, 3, 22.3), (11, 2, 34.9), (15, 2, 45.6), - (21, 1, 15.3), (22, 2, 12.3), (29, 3, 16.3); -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Should now hold data again -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - --- Truncate one of the aggregates, but first test that we block --- TRUNCATE ONLY -\set ON_ERROR_STOP 0 -TRUNCATE ONLY cond_20; -psql:include/cagg_invalidation_common.sql:408: ERROR: cannot truncate only a continuous aggregate -\set ON_ERROR_STOP 1 -TRUNCATE cond_20; --- Should now be empty -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Other aggregate is not affected -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - --- Refresh again to bring data back -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- The aggregate should be populated again -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - -------------------------------------------------------- --- Test corner cases against a minimal bucket aggregate -------------------------------------------------------- --- First, clear the table and aggregate -TRUNCATE conditions; -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CREATE MATERIALIZED VIEW cond_1 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '1', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -SELECT mat_hypertable_id AS cond_1_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_1' \gset --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_cagg_log_add_entry(:cond_1_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test invalidations with bucket size 1 -INSERT INTO conditions VALUES (0, 1, 1.0); -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 0 | 0 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Refreshing around the bucket should not update the aggregate -CALL refresh_continuous_aggregate('cond_1', -1, 0); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Refresh only the invalidated bucket -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 6 | -9223372036854775808 | -2 - 6 | 2 | 9223372036854775807 -(2 rows) - -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - --- Refresh 1 extra bucket on the left -INSERT INTO conditions VALUES (0, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', -1, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1.5 -(1 row) - --- Refresh 1 extra bucket on the right -INSERT INTO conditions VALUES (0, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2 -(1 row) - --- Refresh 1 extra bucket on each side -INSERT INTO conditions VALUES (0, 1, 4.0); -CALL refresh_continuous_aggregate('cond_1', -1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2.5 -(1 row) - --- Clear to reset aggregate -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Test invalidation of size 2 -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); --- Refresh one bucket at a time -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Repeat the same thing but refresh the whole invalidation at once -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Test invalidation of size 3 -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); --- Invalidation extends beyond the refresh window on both ends -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 1 | 1 | 2 -(1 row) - --- Should leave one invalidation on each side of the refresh window -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 0 | 0 - 6 | 2 | 2 - 6 | 110 | 9223372036854775807 -(3 rows) - --- Refresh the two remaining invalidations -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - -CALL refresh_continuous_aggregate('cond_1', 2, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Clear and repeat but instead refresh the whole range in one go. The --- result should be the same as the three partial refreshes. Use --- DELETE instead of TRUNCATE to clear this time. -DELETE FROM conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - ----------------------------------------------- --- Test that invalidation threshold is capped ----------------------------------------------- -CREATE table threshold_test (time int, value int); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('threshold_test', 'time', chunk_time_interval => 4, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:565: WARNING: distributed hypertable is deprecated -psql:include/cagg_invalidation_common.sql:565: NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (7,public,threshold_test,t) -(1 row) - -\else -SELECT create_hypertable('threshold_test', 'time', chunk_time_interval => 4); -\endif -SELECT set_integer_now_func('threshold_test', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW thresh_2 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 WITH NO DATA; -SELECT raw_hypertable_id AS thresh_hyper_id, mat_hypertable_id AS thresh_cagg_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'thresh_2' \gset --- There's no invalidation threshold initially -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_hyper_log_add_entry(:thresh_hyper_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test that threshold is initilized to min value when there's no data --- and we specify an infinite end. Note that the min value may differ --- depending on time type. -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -psql:include/cagg_invalidation_common.sql:599: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - -INSERT INTO threshold_test -SELECT v, v FROM generate_series(1, 10) v; -CALL refresh_continuous_aggregate('thresh_2', 0, 5); --- Threshold should move to end of the last refreshed bucket, which is --- the last bucket fully included in the window, i.e., the window --- shrinks to end of previous bucket. -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 4 -(1 row) - --- Refresh where both the start and end of the window is above the --- max data value -CALL refresh_continuous_aggregate('thresh_2', 14, NULL); -psql:include/cagg_invalidation_common.sql:619: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT watermark AS thresh_hyper_id_watermark -FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id \gset --- Refresh where we start from the current watermark to infinity -CALL refresh_continuous_aggregate('thresh_2', :thresh_hyper_id_watermark, NULL); -psql:include/cagg_invalidation_common.sql:626: NOTICE: continuous aggregate "thresh_2" is already up-to-date --- Now refresh with max end of the window to test that the --- invalidation threshold is capped at the last bucket of data -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Should not have processed invalidations beyond the invalidation --- threshold. -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 12 | 9223372036854775807 -(2 rows) - --- Check that things are properly materialized -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Delete the last data -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('threshold_test') -ORDER BY 1 DESC -LIMIT 1 \gset -DELETE FROM threshold_test -WHERE time > 6; --- The last data in the hypertable is gone -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The aggregate still holds data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Refresh the aggregate to bring it up-to-date -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Data also gone from the aggregate -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The invalidation threshold remains the same -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Insert new data beyond the invalidation threshold to move it --- forward -INSERT INTO threshold_test -SELECT v, v FROM generate_series(7, 15) v; -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Aggregate now updated to reflect newly aggregated data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 11 - 12 | 13 - 14 | 15 -(8 rows) - --- The invalidation threshold should have moved forward to the end of --- the new data -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 16 -(1 row) - --- The aggregate remains invalid beyond the invalidation threshold -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 16 | 9223372036854775807 -(2 rows) - ----------------------------------------------------------------------- --- Test that dropping a chunk invalidates the dropped region. First --- create another chunk so that we have two chunks. One of the chunks --- will be dropped. ---------------------------------------------------------------------- -INSERT INTO conditions VALUES (10, 1, 10.0); --- Chunks currently associated with the hypertable -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions'); - chunk_to_drop ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_34_chunk - _timescaledb_internal._dist_hyper_1_40_chunk -(2 rows) - --- Pick the first one to drop -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before dropping one of the chunks -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 - 10 | 1 | 10 -(4 rows) - --- Drop one chunk -\if :IS_DISTRIBUTED -CALL distributed_exec(format('DROP TABLE IF EXISTS %s', :'chunk_to_drop')); -DROP FOREIGN TABLE :chunk_to_drop; -\else -DROP TABLE :chunk_to_drop; -\endif --- The chunk's data no longer exists in the hypertable -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 10 | 1 | 10 -(1 row) - --- Aggregate still remains in continuous aggregate, however -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Refresh the continuous aggregate to make the dropped data be --- reflected in the aggregate -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Aggregate now up-to-date with the source hypertable -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 10 | 1 | 10 -(1 row) - --- Test that adjacent invalidations are merged -INSERT INTO conditions VALUES(1, 1, 1.0), (2, 1, 2.0); -INSERT INTO conditions VALUES(3, 1, 1.0); -INSERT INTO conditions VALUES(4, 1, 1.0); -INSERT INTO conditions VALUES(6, 1, 1.0); -CALL refresh_continuous_aggregate('cond_1', 10, NULL); -psql:include/cagg_invalidation_common.sql:748: NOTICE: continuous aggregate "cond_1" is already up-to-date -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 1 | 4 - 6 | 6 | 6 - 6 | 110 | 9223372036854775807 -(3 rows) - ---------------------------------------------------------------------- --- Test that single timestamp invalidations are expanded to buckets, --- and adjacent buckets merged. This merging cannot cross Data-Node --- chunk boundaries for the distributed hypertable case. ---------------------------------------------------------------------- --- First clear invalidations in a range: -CALL refresh_continuous_aggregate('cond_10', -20, 60); --- The following three should be merged to one range 0-29 -INSERT INTO conditions VALUES (5, 1, 1.0); -INSERT INTO conditions VALUES (15, 1, 1.0); -INSERT INTO conditions VALUES (25, 1, 1.0); --- The last one should not merge with the others -INSERT INTO conditions VALUES (40, 1, 1.0); --- Refresh to process invalidations, but outside the range of --- invalidations we inserted so that we don't clear them. -CALL refresh_continuous_aggregate('cond_10', 50, 60); -psql:include/cagg_invalidation_common.sql:769: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT mat_hypertable_id AS cond_10_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_10' \gset -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_10_id; -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -21 - 3 | 0 | 9 - 3 | 0 | 19 - 3 | 10 | 29 - 3 | 20 | 29 - 3 | 40 | 49 - 3 | 60 | 9223372036854775807 -(7 rows) - --- should trigger two individual refreshes -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Allow at most 5 individual invalidations per refreshe -SET timescaledb.materializations_per_refresh_window=5; --- Insert into every second bucket -INSERT INTO conditions VALUES (20, 1, 1.0); -INSERT INTO conditions VALUES (40, 1, 1.0); -INSERT INTO conditions VALUES (60, 1, 1.0); -INSERT INTO conditions VALUES (80, 1, 1.0); -INSERT INTO conditions VALUES (100, 1, 1.0); -INSERT INTO conditions VALUES (120, 1, 1.0); -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -\set VERBOSITY default --- Test acceptable values for materializations per refresh -SET timescaledb.materializations_per_refresh_window=' 5 '; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Large value will be treated as LONG_MAX -SET timescaledb.materializations_per_refresh_window=342239897234023842394249234766923492347; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Test bad values for materializations per refresh -SET timescaledb.materializations_per_refresh_window='foo'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:808: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "foo". -SET timescaledb.materializations_per_refresh_window='2bar'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:811: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "2bar". -SET timescaledb.materializations_per_refresh_window='-'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:815: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "-". -\set VERBOSITY terse --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_invalidation_dist_ht-14.out b/tsl/test/expected/cagg_invalidation_dist_ht-14.out deleted file mode 100644 index d567c9b209f..00000000000 --- a/tsl/test/expected/cagg_invalidation_dist_ht-14.out +++ /dev/null @@ -1,2207 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------------+--------------------------------+--------------+------------------+------------------- - db_cagg_invalidation_dist_ht_1 | db_cagg_invalidation_dist_ht_1 | t | t | t - db_cagg_invalidation_dist_ht_2 | db_cagg_invalidation_dist_ht_2 | t | t | t - db_cagg_invalidation_dist_ht_3 | db_cagg_invalidation_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER, :ROLE_DEFAULT_PERM_USER_2; -\set IS_DISTRIBUTED TRUE -\ir include/cagg_invalidation_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. --- Disable background workers since we are testing manual refresh -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT _timescaledb_functions.stop_background_workers(); - stop_background_workers -------------------------- - t -(1 row) - -SET ROLE :ROLE_DEFAULT_PERM_USER; -SET datestyle TO 'ISO, YMD'; -SET timezone TO 'UTC'; -CREATE TABLE conditions (time bigint NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:14: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,conditions,t) -(1 row) - -\else -SELECT create_hypertable('conditions', 'time', chunk_time_interval => 10); -\endif -CREATE TABLE measurements (time int NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('measurements', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:21: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,measurements,t) -(1 row) - -\else -SELECT create_hypertable('measurements', 'time', chunk_time_interval => 10); -\endif -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -$DIST$); -\endif -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -$DIST$); -\endif -SELECT set_integer_now_func('conditions', 'bigint_now'); - set_integer_now_func ----------------------- - -(1 row) - -SELECT set_integer_now_func('measurements', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO conditions -SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::int, - abs(timestamp_hash(to_timestamp(t)::timestamp))%40 -FROM generate_series(1, 100, 1) t; -CREATE TABLE temp AS -SELECT * FROM conditions; -INSERT INTO measurements -SELECT * FROM temp; --- Show the most recent data -SELECT * FROM conditions -ORDER BY time DESC, device -LIMIT 10; - time | device | temp -------+--------+------ - 100 | 0 | 8 - 99 | 1 | 5 - 98 | 2 | 26 - 97 | 2 | 10 - 96 | 2 | 34 - 95 | 2 | 30 - 94 | 3 | 31 - 93 | 0 | 4 - 92 | 0 | 32 - 91 | 3 | 15 -(10 rows) - --- Create two continuous aggregates on the same hypertable to test --- that invalidations are handled correctly across both of them. -CREATE MATERIALIZED VIEW cond_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '10', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW cond_20 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '20', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW measure_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(10, time) AS bucket, device, avg(temp) AS avg_temp -FROM measurements -GROUP BY 1,2 WITH NO DATA; --- There should be three continuous aggregates, two on one hypertable --- and one on the other: -SELECT mat_hypertable_id, raw_hypertable_id, user_view_name -FROM _timescaledb_catalog.continuous_agg; - mat_hypertable_id | raw_hypertable_id | user_view_name --------------------+-------------------+---------------- - 3 | 1 | cond_10 - 4 | 1 | cond_20 - 5 | 2 | measure_10 -(3 rows) - --- The continuous aggregates should be empty -SELECT * FROM cond_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM measure_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -\if :IS_DISTRIBUTED -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT materialization_id AS cagg_id, - lowest_modified_value AS start, - greatest_modified_value AS end - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -\else -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE ( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log - ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE ( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT materialization_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log - ORDER BY 1,2,3 -$$; -\endif -CREATE VIEW hyper_invals AS SELECT * FROM get_hyper_invals(); -CREATE VIEW cagg_invals AS SELECT * FROM get_cagg_invals(); --- Must refresh to move the invalidation threshold, or no --- invalidations will be generated. Initially, threshold is the --- MIN of the time dimension data type: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+---------------------- - 1 | -9223372036854775808 - 2 | -2147483648 -(2 rows) - --- There should be only "infinite" invalidations in the cagg --- invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(3 rows) - --- Now refresh up to 50 without the first bucket, and the threshold should be updated accordingly: -CALL refresh_continuous_aggregate('cond_10', 1, 50); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Invalidations should be cleared inside the refresh window: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refresh up to 50 from the beginning -CALL refresh_continuous_aggregate('cond_10', 0, 50); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing below the threshold does not move it: -CALL refresh_continuous_aggregate('cond_10', 20, 49); -psql:include/cagg_invalidation_common.sql:207: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Nothing changes with invalidations either since the region was --- already refreshed and no new invalidations have been generated: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing measure_10 moves the threshold only for the other hypertable: -CALL refresh_continuous_aggregate('measure_10', 0, 30); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 50 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(5 rows) - --- Refresh on the second continuous aggregate, cond_20, on the first --- hypertable moves the same threshold as when refreshing cond_10: -CALL refresh_continuous_aggregate('cond_20', 60, 100); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- There should be no hypertable invalidations initially: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:229: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- -(0 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Create invalidations across different ranges. Some of these should --- be deleted and others cut in different ways when a refresh is --- run. Note that the refresh window is inclusive in the start of the --- window but exclusive at the end. --- Entries that should be left unmodified: -INSERT INTO conditions VALUES (10, 4, 23.7); -INSERT INTO conditions VALUES (10, 5, 23.8), (19, 3, 23.6); -INSERT INTO conditions VALUES (60, 3, 23.7), (70, 4, 23.7); --- Should see some invaliations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 -(5 rows) - --- Generate some invalidations for the other hypertable -INSERT INTO measurements VALUES (20, 4, 23.7); -INSERT INTO measurements VALUES (30, 5, 23.8), (80, 3, 23.6); --- Should now see invalidations for both hypertables -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 - 2 | 20 | 20 - 2 | 30 | 80 -(7 rows) - --- First refresh a window where we don't have any invalidations. This --- allows us to see only the copying of the invalidations to the per --- cagg log without additional processing. -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidation threshold remains at 100: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log, but only for the hypertable that --- the refreshed aggregate belongs to: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Now add more invalidations to test a refresh that overlaps with them. --- Entries that should be deleted: -INSERT INTO conditions VALUES (30, 1, 23.4), (59, 1, 23.4); -INSERT INTO conditions VALUES (20, 1, 23.4), (30, 1, 23.4); --- Entries that should be cut to the right, leaving an invalidation to --- the left of the refresh window: -INSERT INTO conditions VALUES (1, 4, 23.7), (25, 1, 23.4); -INSERT INTO conditions VALUES (19, 4, 23.7), (59, 1, 23.4); --- Entries that should be cut to the left and right, leaving two --- invalidation entries on each side of the refresh window: -INSERT INTO conditions VALUES (2, 2, 23.5), (60, 1, 23.4); -INSERT INTO conditions VALUES (3, 2, 23.5), (80, 1, 23.4); --- Entries that should be cut to the left, leaving an invalidation to --- the right of the refresh window: -INSERT INTO conditions VALUES (60, 3, 23.6), (90, 3, 23.6); -INSERT INTO conditions VALUES (20, 5, 23.8), (100, 3, 23.6); --- New invalidations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 1 | 1 - 1 | 1 | 25 - 1 | 2 | 60 - 1 | 3 | 3 - 1 | 3 | 80 - 1 | 19 | 19 - 1 | 19 | 59 - 1 | 20 | 20 - 1 | 20 | 30 - 1 | 20 | 100 - 1 | 25 | 25 - 1 | 30 | 30 - 1 | 30 | 59 - 1 | 59 | 59 - 1 | 60 | 90 - 1 | 80 | 80 - 1 | 100 | 100 - 2 | 20 | 20 - 2 | 30 | 80 -(19 rows) - --- But nothing has yet changed in the cagg invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh to process invalidations for daily temperature: -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log. -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Only the cond_10 cagg should have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 0 | 99 - 4 | 0 | 119 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(12 rows) - --- Refresh also cond_20: -CALL refresh_continuous_aggregate('cond_20', 20, 60); --- The cond_20 cagg should also have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - --- Refresh cond_10 to completely remove an invalidation: -CALL refresh_continuous_aggregate('cond_10', 0, 20); --- The 1-19 invalidation should be deleted: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Clear everything between 0 and 100 to make way for new --- invalidations -CALL refresh_continuous_aggregate('cond_10', 0, 100); --- Test refreshing with non-overlapping invalidations -INSERT INTO conditions VALUES (20, 1, 23.4), (25, 1, 23.4); -INSERT INTO conditions VALUES (30, 1, 23.4), (46, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 1, 40); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 40 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh whithout cutting (in area where there are no --- invalidations). Merging of overlapping entries should still happen: -INSERT INTO conditions VALUES (15, 1, 23.4), (42, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 90, 100); -psql:include/cagg_invalidation_common.sql:327: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(10 rows) - --- Test max refresh window -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | 110 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Pick the first chunk of conditions to TRUNCATE -SELECT show_chunks AS chunk_to_truncate -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before truncating one of the chunks -SELECT * FROM :chunk_to_truncate -ORDER BY 1; - time | device | temp -------+--------+------ - 1 | 4 | 23.7 - 1 | 0 | 16 - 2 | 2 | 23.5 - 2 | 1 | 25 - 3 | 2 | 23.5 - 3 | 0 | 20 - 4 | 2 | 10 - 5 | 2 | 26 - 6 | 1 | 13 - 7 | 3 | 35 - 8 | 1 | 37 - 9 | 3 | 7 -(12 rows) - --- Truncate one chunk -\if :IS_DISTRIBUTED --- There is no TRUNCATE implementation for FOREIGN tables yet -\set ON_ERROR_STOP 0 -\endif -TRUNCATE TABLE :chunk_to_truncate; -psql:include/cagg_invalidation_common.sql:352: ERROR: cannot truncate foreign table "_dist_hyper_1_1_chunk" -\if :IS_DISTRIBUTED -\set ON_ERROR_STOP 1 -\endif --- Should see new invalidation entries for conditions for the non-distributed case -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- TRUNCATE the hypertable to invalidate all its continuous aggregates -TRUNCATE conditions; --- Now empty -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - --- Should see an infinite invalidation entry for conditions -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+----------------------+--------------------- - 1 | -9223372036854775808 | 9223372036854775807 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Aggregates still hold data -SELECT * FROM cond_10 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+---------- - 0 | 0 | 18 - 0 | 1 | 25 - 0 | 2 | 20.75 - 0 | 3 | 21 - 0 | 4 | 23.7 -(5 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+------------------ - 20 | 0 | 18.2857142857143 - 20 | 1 | 23.5142857142857 - 20 | 2 | 26 - 20 | 3 | 23 - 20 | 5 | 23.8 -(5 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Both should now be empty after refresh -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Insert new data again and refresh -INSERT INTO conditions VALUES - (1, 1, 23.4), (4, 3, 14.3), (5, 1, 13.6), - (6, 2, 17.9), (12, 1, 18.3), (19, 3, 28.2), - (10, 3, 22.3), (11, 2, 34.9), (15, 2, 45.6), - (21, 1, 15.3), (22, 2, 12.3), (29, 3, 16.3); -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Should now hold data again -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - --- Truncate one of the aggregates, but first test that we block --- TRUNCATE ONLY -\set ON_ERROR_STOP 0 -TRUNCATE ONLY cond_20; -psql:include/cagg_invalidation_common.sql:408: ERROR: cannot truncate only a continuous aggregate -\set ON_ERROR_STOP 1 -TRUNCATE cond_20; --- Should now be empty -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Other aggregate is not affected -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - --- Refresh again to bring data back -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- The aggregate should be populated again -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - -------------------------------------------------------- --- Test corner cases against a minimal bucket aggregate -------------------------------------------------------- --- First, clear the table and aggregate -TRUNCATE conditions; -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CREATE MATERIALIZED VIEW cond_1 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '1', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -SELECT mat_hypertable_id AS cond_1_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_1' \gset --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_cagg_log_add_entry(:cond_1_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test invalidations with bucket size 1 -INSERT INTO conditions VALUES (0, 1, 1.0); -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 0 | 0 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Refreshing around the bucket should not update the aggregate -CALL refresh_continuous_aggregate('cond_1', -1, 0); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Refresh only the invalidated bucket -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 6 | -9223372036854775808 | -2 - 6 | 2 | 9223372036854775807 -(2 rows) - -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - --- Refresh 1 extra bucket on the left -INSERT INTO conditions VALUES (0, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', -1, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1.5 -(1 row) - --- Refresh 1 extra bucket on the right -INSERT INTO conditions VALUES (0, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2 -(1 row) - --- Refresh 1 extra bucket on each side -INSERT INTO conditions VALUES (0, 1, 4.0); -CALL refresh_continuous_aggregate('cond_1', -1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2.5 -(1 row) - --- Clear to reset aggregate -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Test invalidation of size 2 -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); --- Refresh one bucket at a time -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Repeat the same thing but refresh the whole invalidation at once -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Test invalidation of size 3 -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); --- Invalidation extends beyond the refresh window on both ends -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 1 | 1 | 2 -(1 row) - --- Should leave one invalidation on each side of the refresh window -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 0 | 0 - 6 | 2 | 2 - 6 | 110 | 9223372036854775807 -(3 rows) - --- Refresh the two remaining invalidations -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - -CALL refresh_continuous_aggregate('cond_1', 2, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Clear and repeat but instead refresh the whole range in one go. The --- result should be the same as the three partial refreshes. Use --- DELETE instead of TRUNCATE to clear this time. -DELETE FROM conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - ----------------------------------------------- --- Test that invalidation threshold is capped ----------------------------------------------- -CREATE table threshold_test (time int, value int); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('threshold_test', 'time', chunk_time_interval => 4, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:565: WARNING: distributed hypertable is deprecated -psql:include/cagg_invalidation_common.sql:565: NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (7,public,threshold_test,t) -(1 row) - -\else -SELECT create_hypertable('threshold_test', 'time', chunk_time_interval => 4); -\endif -SELECT set_integer_now_func('threshold_test', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW thresh_2 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 WITH NO DATA; -SELECT raw_hypertable_id AS thresh_hyper_id, mat_hypertable_id AS thresh_cagg_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'thresh_2' \gset --- There's no invalidation threshold initially -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_hyper_log_add_entry(:thresh_hyper_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test that threshold is initilized to min value when there's no data --- and we specify an infinite end. Note that the min value may differ --- depending on time type. -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -psql:include/cagg_invalidation_common.sql:599: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - -INSERT INTO threshold_test -SELECT v, v FROM generate_series(1, 10) v; -CALL refresh_continuous_aggregate('thresh_2', 0, 5); --- Threshold should move to end of the last refreshed bucket, which is --- the last bucket fully included in the window, i.e., the window --- shrinks to end of previous bucket. -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 4 -(1 row) - --- Refresh where both the start and end of the window is above the --- max data value -CALL refresh_continuous_aggregate('thresh_2', 14, NULL); -psql:include/cagg_invalidation_common.sql:619: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT watermark AS thresh_hyper_id_watermark -FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id \gset --- Refresh where we start from the current watermark to infinity -CALL refresh_continuous_aggregate('thresh_2', :thresh_hyper_id_watermark, NULL); -psql:include/cagg_invalidation_common.sql:626: NOTICE: continuous aggregate "thresh_2" is already up-to-date --- Now refresh with max end of the window to test that the --- invalidation threshold is capped at the last bucket of data -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Should not have processed invalidations beyond the invalidation --- threshold. -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 12 | 9223372036854775807 -(2 rows) - --- Check that things are properly materialized -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Delete the last data -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('threshold_test') -ORDER BY 1 DESC -LIMIT 1 \gset -DELETE FROM threshold_test -WHERE time > 6; --- The last data in the hypertable is gone -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The aggregate still holds data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Refresh the aggregate to bring it up-to-date -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Data also gone from the aggregate -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The invalidation threshold remains the same -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Insert new data beyond the invalidation threshold to move it --- forward -INSERT INTO threshold_test -SELECT v, v FROM generate_series(7, 15) v; -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Aggregate now updated to reflect newly aggregated data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 11 - 12 | 13 - 14 | 15 -(8 rows) - --- The invalidation threshold should have moved forward to the end of --- the new data -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 16 -(1 row) - --- The aggregate remains invalid beyond the invalidation threshold -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 16 | 9223372036854775807 -(2 rows) - ----------------------------------------------------------------------- --- Test that dropping a chunk invalidates the dropped region. First --- create another chunk so that we have two chunks. One of the chunks --- will be dropped. ---------------------------------------------------------------------- -INSERT INTO conditions VALUES (10, 1, 10.0); --- Chunks currently associated with the hypertable -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions'); - chunk_to_drop ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_34_chunk - _timescaledb_internal._dist_hyper_1_40_chunk -(2 rows) - --- Pick the first one to drop -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before dropping one of the chunks -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 - 10 | 1 | 10 -(4 rows) - --- Drop one chunk -\if :IS_DISTRIBUTED -CALL distributed_exec(format('DROP TABLE IF EXISTS %s', :'chunk_to_drop')); -DROP FOREIGN TABLE :chunk_to_drop; -\else -DROP TABLE :chunk_to_drop; -\endif --- The chunk's data no longer exists in the hypertable -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 10 | 1 | 10 -(1 row) - --- Aggregate still remains in continuous aggregate, however -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Refresh the continuous aggregate to make the dropped data be --- reflected in the aggregate -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Aggregate now up-to-date with the source hypertable -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 10 | 1 | 10 -(1 row) - --- Test that adjacent invalidations are merged -INSERT INTO conditions VALUES(1, 1, 1.0), (2, 1, 2.0); -INSERT INTO conditions VALUES(3, 1, 1.0); -INSERT INTO conditions VALUES(4, 1, 1.0); -INSERT INTO conditions VALUES(6, 1, 1.0); -CALL refresh_continuous_aggregate('cond_1', 10, NULL); -psql:include/cagg_invalidation_common.sql:748: NOTICE: continuous aggregate "cond_1" is already up-to-date -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 1 | 4 - 6 | 6 | 6 - 6 | 110 | 9223372036854775807 -(3 rows) - ---------------------------------------------------------------------- --- Test that single timestamp invalidations are expanded to buckets, --- and adjacent buckets merged. This merging cannot cross Data-Node --- chunk boundaries for the distributed hypertable case. ---------------------------------------------------------------------- --- First clear invalidations in a range: -CALL refresh_continuous_aggregate('cond_10', -20, 60); --- The following three should be merged to one range 0-29 -INSERT INTO conditions VALUES (5, 1, 1.0); -INSERT INTO conditions VALUES (15, 1, 1.0); -INSERT INTO conditions VALUES (25, 1, 1.0); --- The last one should not merge with the others -INSERT INTO conditions VALUES (40, 1, 1.0); --- Refresh to process invalidations, but outside the range of --- invalidations we inserted so that we don't clear them. -CALL refresh_continuous_aggregate('cond_10', 50, 60); -psql:include/cagg_invalidation_common.sql:769: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT mat_hypertable_id AS cond_10_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_10' \gset -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_10_id; -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -21 - 3 | 0 | 9 - 3 | 0 | 19 - 3 | 10 | 29 - 3 | 20 | 29 - 3 | 40 | 49 - 3 | 60 | 9223372036854775807 -(7 rows) - --- should trigger two individual refreshes -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Allow at most 5 individual invalidations per refreshe -SET timescaledb.materializations_per_refresh_window=5; --- Insert into every second bucket -INSERT INTO conditions VALUES (20, 1, 1.0); -INSERT INTO conditions VALUES (40, 1, 1.0); -INSERT INTO conditions VALUES (60, 1, 1.0); -INSERT INTO conditions VALUES (80, 1, 1.0); -INSERT INTO conditions VALUES (100, 1, 1.0); -INSERT INTO conditions VALUES (120, 1, 1.0); -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -\set VERBOSITY default --- Test acceptable values for materializations per refresh -SET timescaledb.materializations_per_refresh_window=' 5 '; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Large value will be treated as LONG_MAX -SET timescaledb.materializations_per_refresh_window=342239897234023842394249234766923492347; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Test bad values for materializations per refresh -SET timescaledb.materializations_per_refresh_window='foo'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:808: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "foo". -SET timescaledb.materializations_per_refresh_window='2bar'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:811: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "2bar". -SET timescaledb.materializations_per_refresh_window='-'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:815: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "-". -\set VERBOSITY terse --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_invalidation_dist_ht-15.out b/tsl/test/expected/cagg_invalidation_dist_ht-15.out deleted file mode 100644 index d567c9b209f..00000000000 --- a/tsl/test/expected/cagg_invalidation_dist_ht-15.out +++ /dev/null @@ -1,2207 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------------+--------------------------------+--------------+------------------+------------------- - db_cagg_invalidation_dist_ht_1 | db_cagg_invalidation_dist_ht_1 | t | t | t - db_cagg_invalidation_dist_ht_2 | db_cagg_invalidation_dist_ht_2 | t | t | t - db_cagg_invalidation_dist_ht_3 | db_cagg_invalidation_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER, :ROLE_DEFAULT_PERM_USER_2; -\set IS_DISTRIBUTED TRUE -\ir include/cagg_invalidation_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. --- Disable background workers since we are testing manual refresh -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT _timescaledb_functions.stop_background_workers(); - stop_background_workers -------------------------- - t -(1 row) - -SET ROLE :ROLE_DEFAULT_PERM_USER; -SET datestyle TO 'ISO, YMD'; -SET timezone TO 'UTC'; -CREATE TABLE conditions (time bigint NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:14: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,conditions,t) -(1 row) - -\else -SELECT create_hypertable('conditions', 'time', chunk_time_interval => 10); -\endif -CREATE TABLE measurements (time int NOT NULL, device int, temp float); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('measurements', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:21: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,measurements,t) -(1 row) - -\else -SELECT create_hypertable('measurements', 'time', chunk_time_interval => 10); -\endif -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION bigint_now() -RETURNS bigint LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM conditions -$$; -$DIST$); -\endif -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -\if :IS_DISTRIBUTED -CALL distributed_exec($DIST$ -CREATE OR REPLACE FUNCTION int_now() -RETURNS int LANGUAGE SQL STABLE AS -$$ - SELECT coalesce(max(time), 0) - FROM measurements -$$; -$DIST$); -\endif -SELECT set_integer_now_func('conditions', 'bigint_now'); - set_integer_now_func ----------------------- - -(1 row) - -SELECT set_integer_now_func('measurements', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO conditions -SELECT t, ceil(abs(timestamp_hash(to_timestamp(t)::timestamp))%4)::int, - abs(timestamp_hash(to_timestamp(t)::timestamp))%40 -FROM generate_series(1, 100, 1) t; -CREATE TABLE temp AS -SELECT * FROM conditions; -INSERT INTO measurements -SELECT * FROM temp; --- Show the most recent data -SELECT * FROM conditions -ORDER BY time DESC, device -LIMIT 10; - time | device | temp -------+--------+------ - 100 | 0 | 8 - 99 | 1 | 5 - 98 | 2 | 26 - 97 | 2 | 10 - 96 | 2 | 34 - 95 | 2 | 30 - 94 | 3 | 31 - 93 | 0 | 4 - 92 | 0 | 32 - 91 | 3 | 15 -(10 rows) - --- Create two continuous aggregates on the same hypertable to test --- that invalidations are handled correctly across both of them. -CREATE MATERIALIZED VIEW cond_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '10', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW cond_20 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '20', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -CREATE MATERIALIZED VIEW measure_10 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(10, time) AS bucket, device, avg(temp) AS avg_temp -FROM measurements -GROUP BY 1,2 WITH NO DATA; --- There should be three continuous aggregates, two on one hypertable --- and one on the other: -SELECT mat_hypertable_id, raw_hypertable_id, user_view_name -FROM _timescaledb_catalog.continuous_agg; - mat_hypertable_id | raw_hypertable_id | user_view_name --------------------+-------------------+---------------- - 3 | 1 | cond_10 - 4 | 1 | cond_20 - 5 | 2 | measure_10 -(3 rows) - --- The continuous aggregates should be empty -SELECT * FROM cond_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM measure_10 -ORDER BY 1 DESC, 2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -\if :IS_DISTRIBUTED -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT DISTINCT table_record[1]::TEXT::INT, table_record[2]::TEXT::BIGINT, table_record[3]::TEXT::BIGINT FROM test.remote_exec_get_result_strings(NULL, $DIST$ - SELECT materialization_id AS cagg_id, - lowest_modified_value AS start, - greatest_modified_value AS end - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log -$DIST$) -ORDER BY 1,2,3 -$$; -\else -CREATE OR REPLACE FUNCTION get_hyper_invals() RETURNS TABLE ( - "hyper_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT hypertable_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log - ORDER BY 1,2,3 -$$; -CREATE OR REPLACE FUNCTION get_cagg_invals() RETURNS TABLE ( - "cagg_id" INT, - "start" BIGINT, - "end" BIGINT -) -LANGUAGE SQL VOLATILE AS -$$ -SELECT materialization_id, - lowest_modified_value, - greatest_modified_value - FROM _timescaledb_catalog.continuous_aggs_materialization_invalidation_log - ORDER BY 1,2,3 -$$; -\endif -CREATE VIEW hyper_invals AS SELECT * FROM get_hyper_invals(); -CREATE VIEW cagg_invals AS SELECT * FROM get_cagg_invals(); --- Must refresh to move the invalidation threshold, or no --- invalidations will be generated. Initially, threshold is the --- MIN of the time dimension data type: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+---------------------- - 1 | -9223372036854775808 - 2 | -2147483648 -(2 rows) - --- There should be only "infinite" invalidations in the cagg --- invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:192: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(3 rows) - --- Now refresh up to 50 without the first bucket, and the threshold should be updated accordingly: -CALL refresh_continuous_aggregate('cond_10', 1, 50); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Invalidations should be cleared inside the refresh window: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:200: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | 9 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refresh up to 50 from the beginning -CALL refresh_continuous_aggregate('cond_10', 0, 50); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:204: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing below the threshold does not move it: -CALL refresh_continuous_aggregate('cond_10', 20, 49); -psql:include/cagg_invalidation_common.sql:207: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 1 | 50 - 2 | -2147483648 -(2 rows) - --- Nothing changes with invalidations either since the region was --- already refreshed and no new invalidations have been generated: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:213: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | 9223372036854775807 -(4 rows) - --- Refreshing measure_10 moves the threshold only for the other hypertable: -CALL refresh_continuous_aggregate('measure_10', 0, 30); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 50 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:219: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(5 rows) - --- Refresh on the second continuous aggregate, cond_20, on the first --- hypertable moves the same threshold as when refreshing cond_10: -CALL refresh_continuous_aggregate('cond_20', 60, 100); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:226: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- There should be no hypertable invalidations initially: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:229: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- -(0 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:230: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 50 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Create invalidations across different ranges. Some of these should --- be deleted and others cut in different ways when a refresh is --- run. Note that the refresh window is inclusive in the start of the --- window but exclusive at the end. --- Entries that should be left unmodified: -INSERT INTO conditions VALUES (10, 4, 23.7); -INSERT INTO conditions VALUES (10, 5, 23.8), (19, 3, 23.6); -INSERT INTO conditions VALUES (60, 3, 23.7), (70, 4, 23.7); --- Should see some invaliations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:243: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 -(5 rows) - --- Generate some invalidations for the other hypertable -INSERT INTO measurements VALUES (20, 4, 23.7); -INSERT INTO measurements VALUES (30, 5, 23.8), (80, 3, 23.6); --- Should now see invalidations for both hypertables -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:250: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 10 | 10 - 1 | 10 | 19 - 1 | 60 | 60 - 1 | 60 | 70 - 1 | 70 | 70 - 2 | 20 | 20 - 2 | 30 | 80 -(7 rows) - --- First refresh a window where we don't have any invalidations. This --- allows us to see only the copying of the invalidations to the per --- cagg log without additional processing. -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidation threshold remains at 100: -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 1 | 100 - 2 | 30 -(2 rows) - --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log, but only for the hypertable that --- the refreshed aggregate belongs to: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:263: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:264: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Now add more invalidations to test a refresh that overlaps with them. --- Entries that should be deleted: -INSERT INTO conditions VALUES (30, 1, 23.4), (59, 1, 23.4); -INSERT INTO conditions VALUES (20, 1, 23.4), (30, 1, 23.4); --- Entries that should be cut to the right, leaving an invalidation to --- the left of the refresh window: -INSERT INTO conditions VALUES (1, 4, 23.7), (25, 1, 23.4); -INSERT INTO conditions VALUES (19, 4, 23.7), (59, 1, 23.4); --- Entries that should be cut to the left and right, leaving two --- invalidation entries on each side of the refresh window: -INSERT INTO conditions VALUES (2, 2, 23.5), (60, 1, 23.4); -INSERT INTO conditions VALUES (3, 2, 23.5), (80, 1, 23.4); --- Entries that should be cut to the left, leaving an invalidation to --- the right of the refresh window: -INSERT INTO conditions VALUES (60, 3, 23.6), (90, 3, 23.6); -INSERT INTO conditions VALUES (20, 5, 23.8), (100, 3, 23.6); --- New invalidations in the hypertable invalidation log: -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:284: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 1 | 1 - 1 | 1 | 25 - 1 | 2 | 60 - 1 | 3 | 3 - 1 | 3 | 80 - 1 | 19 | 19 - 1 | 19 | 59 - 1 | 20 | 20 - 1 | 20 | 30 - 1 | 20 | 100 - 1 | 25 | 25 - 1 | 30 | 30 - 1 | 30 | 59 - 1 | 59 | 59 - 1 | 60 | 90 - 1 | 80 | 80 - 1 | 100 | 100 - 2 | 20 | 20 - 2 | 30 | 80 -(19 rows) - --- But nothing has yet changed in the cagg invalidation log: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:287: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh to process invalidations for daily temperature: -CALL refresh_continuous_aggregate('cond_10', 20, 60); --- Invalidations should be moved from the hypertable invalidation log --- to the continuous aggregate log. -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:294: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Only the cond_10 cagg should have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:297: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 59 - 4 | 0 | 19 - 4 | 0 | 99 - 4 | 0 | 119 - 4 | 60 | 79 - 4 | 100 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(12 rows) - --- Refresh also cond_20: -CALL refresh_continuous_aggregate('cond_20', 20, 60); --- The cond_20 cagg should also have its entries cut: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:303: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | -9223372036854775808 | 19 - 3 | 10 | 19 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - --- Refresh cond_10 to completely remove an invalidation: -CALL refresh_continuous_aggregate('cond_10', 0, 20); --- The 1-19 invalidation should be deleted: -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:309: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 60 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(6 rows) - --- Clear everything between 0 and 100 to make way for new --- invalidations -CALL refresh_continuous_aggregate('cond_10', 0, 100); --- Test refreshing with non-overlapping invalidations -INSERT INTO conditions VALUES (20, 1, 23.4), (25, 1, 23.4); -INSERT INTO conditions VALUES (30, 1, 23.4), (46, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 1, 40); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:321: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 40 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(9 rows) - --- Refresh whithout cutting (in area where there are no --- invalidations). Merging of overlapping entries should still happen: -INSERT INTO conditions VALUES (15, 1, 23.4), (42, 1, 23.4); -CALL refresh_continuous_aggregate('cond_10', 90, 100); -psql:include/cagg_invalidation_common.sql:327: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:329: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -1 - 3 | 10 | 49 - 3 | 100 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(10 rows) - --- Test max refresh window -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cagg_invals; -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:334: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | 110 | 9223372036854775807 - 4 | -9223372036854775808 | 19 - 4 | 0 | 59 - 4 | 20 | 39 - 4 | 20 | 59 - 4 | 60 | 9223372036854775807 - 5 | -9223372036854775808 | -1 - 5 | 30 | 9223372036854775807 -(8 rows) - -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:335: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- Pick the first chunk of conditions to TRUNCATE -SELECT show_chunks AS chunk_to_truncate -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before truncating one of the chunks -SELECT * FROM :chunk_to_truncate -ORDER BY 1; - time | device | temp -------+--------+------ - 1 | 4 | 23.7 - 1 | 0 | 16 - 2 | 2 | 23.5 - 2 | 1 | 25 - 3 | 2 | 23.5 - 3 | 0 | 20 - 4 | 2 | 10 - 5 | 2 | 26 - 6 | 1 | 13 - 7 | 3 | 35 - 8 | 1 | 37 - 9 | 3 | 7 -(12 rows) - --- Truncate one chunk -\if :IS_DISTRIBUTED --- There is no TRUNCATE implementation for FOREIGN tables yet -\set ON_ERROR_STOP 0 -\endif -TRUNCATE TABLE :chunk_to_truncate; -psql:include/cagg_invalidation_common.sql:352: ERROR: cannot truncate foreign table "_dist_hyper_1_1_chunk" -\if :IS_DISTRIBUTED -\set ON_ERROR_STOP 1 -\endif --- Should see new invalidation entries for conditions for the non-distributed case -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:358: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 2 | 20 | 20 - 2 | 30 | 80 -(2 rows) - --- TRUNCATE the hypertable to invalidate all its continuous aggregates -TRUNCATE conditions; --- Now empty -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - --- Should see an infinite invalidation entry for conditions -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:367: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+----------------------+--------------------- - 1 | -9223372036854775808 | 9223372036854775807 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Aggregates still hold data -SELECT * FROM cond_10 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+---------- - 0 | 0 | 18 - 0 | 1 | 25 - 0 | 2 | 20.75 - 0 | 3 | 21 - 0 | 4 | 23.7 -(5 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2 -LIMIT 5; - bucket | device | avg_temp ---------+--------+------------------ - 20 | 0 | 18.2857142857143 - 20 | 1 | 23.5142857142857 - 20 | 2 | 26 - 20 | 3 | 23 - 20 | 5 | 23.8 -(5 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Both should now be empty after refresh -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Insert new data again and refresh -INSERT INTO conditions VALUES - (1, 1, 23.4), (4, 3, 14.3), (5, 1, 13.6), - (6, 2, 17.9), (12, 1, 18.3), (19, 3, 28.2), - (10, 3, 22.3), (11, 2, 34.9), (15, 2, 45.6), - (21, 1, 15.3), (22, 2, 12.3), (29, 3, 16.3); -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- Should now hold data again -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - --- Truncate one of the aggregates, but first test that we block --- TRUNCATE ONLY -\set ON_ERROR_STOP 0 -TRUNCATE ONLY cond_20; -psql:include/cagg_invalidation_common.sql:408: ERROR: cannot truncate only a continuous aggregate -\set ON_ERROR_STOP 1 -TRUNCATE cond_20; --- Should now be empty -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Other aggregate is not affected -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 18.5 - 0 | 2 | 17.9 - 0 | 3 | 14.3 - 10 | 1 | 18.3 - 10 | 2 | 40.25 - 10 | 3 | 25.25 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(9 rows) - --- Refresh again to bring data back -CALL refresh_continuous_aggregate('cond_20', NULL, NULL); --- The aggregate should be populated again -SELECT * FROM cond_20 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+------------------ - 0 | 1 | 18.4333333333333 - 0 | 2 | 32.8 - 0 | 3 | 21.6 - 20 | 1 | 15.3 - 20 | 2 | 12.3 - 20 | 3 | 16.3 -(6 rows) - -------------------------------------------------------- --- Test corner cases against a minimal bucket aggregate -------------------------------------------------------- --- First, clear the table and aggregate -TRUNCATE conditions; -SELECT * FROM conditions; - time | device | temp -------+--------+------ -(0 rows) - -CALL refresh_continuous_aggregate('cond_10', NULL, NULL); -SELECT * FROM cond_10 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CREATE MATERIALIZED VIEW cond_1 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(BIGINT '1', time) AS bucket, device, avg(temp) AS avg_temp -FROM conditions -GROUP BY 1,2 WITH NO DATA; -SELECT mat_hypertable_id AS cond_1_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_1' \gset --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_cagg_log_add_entry(:cond_1_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test invalidations with bucket size 1 -INSERT INTO conditions VALUES (0, 1, 1.0); -SELECT * FROM hyper_invals; -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:463: WARNING: getting results from remote command execution is deprecated - hyper_id | start | end -----------+-------+----- - 1 | 0 | 0 - 2 | 20 | 20 - 2 | 30 | 80 -(3 rows) - --- Refreshing around the bucket should not update the aggregate -CALL refresh_continuous_aggregate('cond_1', -1, 0); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- -(0 rows) - --- Refresh only the invalidated bucket -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:477: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 6 | -9223372036854775808 | -2 - 6 | 2 | 9223372036854775807 -(2 rows) - -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - --- Refresh 1 extra bucket on the left -INSERT INTO conditions VALUES (0, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', -1, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1.5 -(1 row) - --- Refresh 1 extra bucket on the right -INSERT INTO conditions VALUES (0, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2 -(1 row) - --- Refresh 1 extra bucket on each side -INSERT INTO conditions VALUES (0, 1, 4.0); -CALL refresh_continuous_aggregate('cond_1', -1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 2.5 -(1 row) - --- Clear to reset aggregate -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Test invalidation of size 2 -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); --- Refresh one bucket at a time -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 -(1 row) - -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Repeat the same thing but refresh the whole invalidation at once -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0); -CALL refresh_continuous_aggregate('cond_1', 0, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - --- Test invalidation of size 3 -TRUNCATE conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); --- Invalidation extends beyond the refresh window on both ends -CALL refresh_continuous_aggregate('cond_1', 1, 2); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 1 | 1 | 2 -(1 row) - --- Should leave one invalidation on each side of the refresh window -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:538: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 0 | 0 - 6 | 2 | 2 - 6 | 110 | 9223372036854775807 -(3 rows) - --- Refresh the two remaining invalidations -CALL refresh_continuous_aggregate('cond_1', 0, 1); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 -(2 rows) - -CALL refresh_continuous_aggregate('cond_1', 2, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Clear and repeat but instead refresh the whole range in one go. The --- result should be the same as the three partial refreshes. Use --- DELETE instead of TRUNCATE to clear this time. -DELETE FROM conditions; -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); -INSERT INTO conditions VALUES (0, 1, 1.0), (1, 1, 2.0), (2, 1, 3.0); -CALL refresh_continuous_aggregate('cond_1', 0, 3); -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - ----------------------------------------------- --- Test that invalidation threshold is capped ----------------------------------------------- -CREATE table threshold_test (time int, value int); -\if :IS_DISTRIBUTED -SELECT create_distributed_hypertable('threshold_test', 'time', chunk_time_interval => 4, replication_factor => 2); -psql:include/cagg_invalidation_common.sql:565: WARNING: distributed hypertable is deprecated -psql:include/cagg_invalidation_common.sql:565: NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (7,public,threshold_test,t) -(1 row) - -\else -SELECT create_hypertable('threshold_test', 'time', chunk_time_interval => 4); -\endif -SELECT set_integer_now_func('threshold_test', 'int_now'); - set_integer_now_func ----------------------- - -(1 row) - -CREATE MATERIALIZED VIEW thresh_2 -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 WITH NO DATA; -SELECT raw_hypertable_id AS thresh_hyper_id, mat_hypertable_id AS thresh_cagg_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'thresh_2' \gset --- There's no invalidation threshold initially -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - --- Test manual invalidation error -\if :IS_DISTRIBUTED -\else -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.invalidation_hyper_log_add_entry(:thresh_hyper_id, 1, 0); -\set ON_ERROR_STOP 1 -\endif --- Test that threshold is initilized to min value when there's no data --- and we specify an infinite end. Note that the min value may differ --- depending on time type. -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -psql:include/cagg_invalidation_common.sql:599: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+------------- - 7 | -2147483648 -(1 row) - -INSERT INTO threshold_test -SELECT v, v FROM generate_series(1, 10) v; -CALL refresh_continuous_aggregate('thresh_2', 0, 5); --- Threshold should move to end of the last refreshed bucket, which is --- the last bucket fully included in the window, i.e., the window --- shrinks to end of previous bucket. -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 4 -(1 row) - --- Refresh where both the start and end of the window is above the --- max data value -CALL refresh_continuous_aggregate('thresh_2', 14, NULL); -psql:include/cagg_invalidation_common.sql:619: NOTICE: continuous aggregate "thresh_2" is already up-to-date -SELECT watermark AS thresh_hyper_id_watermark -FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id \gset --- Refresh where we start from the current watermark to infinity -CALL refresh_continuous_aggregate('thresh_2', :thresh_hyper_id_watermark, NULL); -psql:include/cagg_invalidation_common.sql:626: NOTICE: continuous aggregate "thresh_2" is already up-to-date --- Now refresh with max end of the window to test that the --- invalidation threshold is capped at the last bucket of data -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Should not have processed invalidations beyond the invalidation --- threshold. -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:639: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 12 | 9223372036854775807 -(2 rows) - --- Check that things are properly materialized -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Delete the last data -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('threshold_test') -ORDER BY 1 DESC -LIMIT 1 \gset -DELETE FROM threshold_test -WHERE time > 6; --- The last data in the hypertable is gone -SELECT time_bucket(2, time) AS bucket, max(value) AS max -FROM threshold_test -GROUP BY 1 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The aggregate still holds data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 10 -(6 rows) - --- Refresh the aggregate to bring it up-to-date -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Data also gone from the aggregate -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 6 -(4 rows) - --- The invalidation threshold remains the same -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 12 -(1 row) - --- Insert new data beyond the invalidation threshold to move it --- forward -INSERT INTO threshold_test -SELECT v, v FROM generate_series(7, 15) v; -CALL refresh_continuous_aggregate('thresh_2', 0, NULL); --- Aggregate now updated to reflect newly aggregated data -SELECT * FROM thresh_2 -ORDER BY 1; - bucket | max ---------+----- - 0 | 1 - 2 | 3 - 4 | 5 - 6 | 7 - 8 | 9 - 10 | 11 - 12 | 13 - 14 | 15 -(8 rows) - --- The invalidation threshold should have moved forward to the end of --- the new data -SELECT * FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold -WHERE hypertable_id = :thresh_hyper_id -ORDER BY 1,2; - hypertable_id | watermark ----------------+----------- - 7 | 16 -(1 row) - --- The aggregate remains invalid beyond the invalidation threshold -SELECT * FROM cagg_invals -WHERE cagg_id = :thresh_cagg_id; -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:695: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 8 | -9223372036854775808 | -1 - 8 | 16 | 9223372036854775807 -(2 rows) - ----------------------------------------------------------------------- --- Test that dropping a chunk invalidates the dropped region. First --- create another chunk so that we have two chunks. One of the chunks --- will be dropped. ---------------------------------------------------------------------- -INSERT INTO conditions VALUES (10, 1, 10.0); --- Chunks currently associated with the hypertable -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions'); - chunk_to_drop ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_34_chunk - _timescaledb_internal._dist_hyper_1_40_chunk -(2 rows) - --- Pick the first one to drop -SELECT show_chunks AS chunk_to_drop -FROM show_chunks('conditions') -ORDER BY 1 -LIMIT 1 \gset --- Show the data before dropping one of the chunks -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 - 10 | 1 | 10 -(4 rows) - --- Drop one chunk -\if :IS_DISTRIBUTED -CALL distributed_exec(format('DROP TABLE IF EXISTS %s', :'chunk_to_drop')); -DROP FOREIGN TABLE :chunk_to_drop; -\else -DROP TABLE :chunk_to_drop; -\endif --- The chunk's data no longer exists in the hypertable -SELECT * FROM conditions -ORDER BY 1,2; - time | device | temp -------+--------+------ - 10 | 1 | 10 -(1 row) - --- Aggregate still remains in continuous aggregate, however -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 0 | 1 | 1 - 1 | 1 | 2 - 2 | 1 | 3 -(3 rows) - --- Refresh the continuous aggregate to make the dropped data be --- reflected in the aggregate -CALL refresh_continuous_aggregate('cond_1', NULL, NULL); --- Aggregate now up-to-date with the source hypertable -SELECT * FROM cond_1 -ORDER BY 1,2; - bucket | device | avg_temp ---------+--------+---------- - 10 | 1 | 10 -(1 row) - --- Test that adjacent invalidations are merged -INSERT INTO conditions VALUES(1, 1, 1.0), (2, 1, 2.0); -INSERT INTO conditions VALUES(3, 1, 1.0); -INSERT INTO conditions VALUES(4, 1, 1.0); -INSERT INTO conditions VALUES(6, 1, 1.0); -CALL refresh_continuous_aggregate('cond_1', 10, NULL); -psql:include/cagg_invalidation_common.sql:748: NOTICE: continuous aggregate "cond_1" is already up-to-date -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_1_id; -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:750: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+-------+--------------------- - 6 | 1 | 4 - 6 | 6 | 6 - 6 | 110 | 9223372036854775807 -(3 rows) - ---------------------------------------------------------------------- --- Test that single timestamp invalidations are expanded to buckets, --- and adjacent buckets merged. This merging cannot cross Data-Node --- chunk boundaries for the distributed hypertable case. ---------------------------------------------------------------------- --- First clear invalidations in a range: -CALL refresh_continuous_aggregate('cond_10', -20, 60); --- The following three should be merged to one range 0-29 -INSERT INTO conditions VALUES (5, 1, 1.0); -INSERT INTO conditions VALUES (15, 1, 1.0); -INSERT INTO conditions VALUES (25, 1, 1.0); --- The last one should not merge with the others -INSERT INTO conditions VALUES (40, 1, 1.0); --- Refresh to process invalidations, but outside the range of --- invalidations we inserted so that we don't clear them. -CALL refresh_continuous_aggregate('cond_10', 50, 60); -psql:include/cagg_invalidation_common.sql:769: NOTICE: continuous aggregate "cond_10" is already up-to-date -SELECT mat_hypertable_id AS cond_10_id -FROM _timescaledb_catalog.continuous_agg -WHERE user_view_name = 'cond_10' \gset -SELECT * FROM cagg_invals -WHERE cagg_id = :cond_10_id; -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated -psql:include/cagg_invalidation_common.sql:776: WARNING: getting results from remote command execution is deprecated - cagg_id | start | end ----------+----------------------+--------------------- - 3 | -9223372036854775808 | -21 - 3 | 0 | 9 - 3 | 0 | 19 - 3 | 10 | 29 - 3 | 20 | 29 - 3 | 40 | 49 - 3 | 60 | 9223372036854775807 -(7 rows) - --- should trigger two individual refreshes -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Allow at most 5 individual invalidations per refreshe -SET timescaledb.materializations_per_refresh_window=5; --- Insert into every second bucket -INSERT INTO conditions VALUES (20, 1, 1.0); -INSERT INTO conditions VALUES (40, 1, 1.0); -INSERT INTO conditions VALUES (60, 1, 1.0); -INSERT INTO conditions VALUES (80, 1, 1.0); -INSERT INTO conditions VALUES (100, 1, 1.0); -INSERT INTO conditions VALUES (120, 1, 1.0); -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -\set VERBOSITY default --- Test acceptable values for materializations per refresh -SET timescaledb.materializations_per_refresh_window=' 5 '; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Large value will be treated as LONG_MAX -SET timescaledb.materializations_per_refresh_window=342239897234023842394249234766923492347; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); --- Test bad values for materializations per refresh -SET timescaledb.materializations_per_refresh_window='foo'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:808: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "foo". -SET timescaledb.materializations_per_refresh_window='2bar'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:811: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "2bar". -SET timescaledb.materializations_per_refresh_window='-'; -INSERT INTO conditions VALUES (140, 1, 1.0); -CALL refresh_continuous_aggregate('cond_10', 0, 200); -psql:include/cagg_invalidation_common.sql:815: WARNING: invalid value for session variable "timescaledb.materializations_per_refresh_window" -DETAIL: Expected an integer but current value is "-". -\set VERBOSITY terse --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_migrate_dist_ht.out b/tsl/test/expected/cagg_migrate_dist_ht.out deleted file mode 100644 index c772effae95..00000000000 --- a/tsl/test/expected/cagg_migrate_dist_ht.out +++ /dev/null @@ -1,2128 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ----------------------------+---------------------------+--------------+------------------+------------------- - db_cagg_migrate_dist_ht_1 | db_cagg_migrate_dist_ht_1 | t | t | t - db_cagg_migrate_dist_ht_2 | db_cagg_migrate_dist_ht_2 | t | t | t - db_cagg_migrate_dist_ht_3 | db_cagg_migrate_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -\set IS_DISTRIBUTED TRUE --- ######################################################## --- ## INTEGER data type tests --- ######################################################## -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\ir include/cagg_migrate_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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -CREATE TABLE conditions ( - "time" :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC -); -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_migrate_common.sql:22: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) - SELECT - generate_series('2022-01-01 00:00:00-00'::timestamptz, '2022-12-31 23:59:59-00'::timestamptz, '1 hour'), - 0.25; -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM public.conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM public.conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - set_integer_now_func ----------------------- - -(1 row) - - INSERT INTO conditions ("time", temperature) - SELECT - generate_series(1, 1000, 1), - 0.25; -\endif --- new cagg format (finalized=true) -CREATE MATERIALIZED VIEW conditions_summary_daily_new -WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket -WITH NO DATA; --- older continuous aggregate to be migrated -CREATE MATERIALIZED VIEW conditions_summary_daily -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:95: NOTICE: refreshing continuous aggregate "conditions_summary_daily" --- for permission tests -CREATE MATERIALIZED VIEW conditions_summary_weekly -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 week', "time") AS bucket, -\else - time_bucket(INTEGER '168', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:113: NOTICE: refreshing continuous aggregate "conditions_summary_weekly" -\set ON_ERROR_STOP 0 --- should fail because we don't need to migrate finalized caggs -CALL cagg_migrate('conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:117: ERROR: continuous aggregate "public.conditions_summary_daily_new" does not require any migration -\set ON_ERROR_STOP 1 -\set ON_ERROR_STOP 0 --- should fail relation does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:122: ERROR: relation "conditions_summary_not_cagg" does not exist at character 19 -CREATE TABLE conditions_summary_not_cagg(); --- should fail continuous agg does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:125: ERROR: continuous aggregate "public.conditions_summary_not_cagg" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE conditions_summary_not_cagg; -SELECT - ca.raw_hypertable_id AS "RAW_HYPERTABLE_ID", - h.schema_name AS "MAT_SCHEMA_NAME", - h.table_name AS "MAT_TABLE_NAME", - partial_view_name AS "PART_VIEW_NAME", - partial_view_schema AS "PART_VIEW_SCHEMA", - direct_view_name AS "DIR_VIEW_NAME", - direct_view_schema AS "DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily' -\gset -\set ON_ERROR_STOP 0 --- should fail because the new cagg with suffix '_new' already exists -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:147: ERROR: continuous aggregate "public.conditions_summary_daily_new" already exists -\set ON_ERROR_STOP 1 --- remove the new cagg to execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; --- get and set all the cagg data -SELECT - _timescaledb_functions.cagg_migrate_pre_validation( - 'public', - 'conditions_summary_daily', - 'conditions_summary_daily_new' - ) AS "CAGG_DATA" -\gset -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -\x on -SELECT mat_hypertable_id, user_view_definition FROM _timescaledb_catalog.continuous_agg_migrate_plan; --[ RECORD 1 ]--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -mat_hypertable_id | 3 -user_view_definition | SELECT _materialized_hypertable_3.bucket, + - | _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_2_2, NULL::numeric) AS min,+ - | _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_3_3, NULL::numeric) AS max,+ - | _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_4_4, NULL::numeric) AS avg,+ - | _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_5_5, NULL::numeric) AS sum + - | FROM _timescaledb_internal._materialized_hypertable_3 + - | WHERE (_materialized_hypertable_3.bucket < COALESCE((_timescaledb_functions.cagg_watermark(3))::integer, '-2147483648'::integer)) + - | GROUP BY _materialized_hypertable_3.bucket + - | UNION ALL + - | SELECT public.time_bucket(24, conditions."time") AS bucket, + - | min(conditions.temperature) AS min, + - | max(conditions.temperature) AS max, + - | avg(conditions.temperature) AS avg, + - | sum(conditions.temperature) AS sum + - | FROM public.conditions + - | WHERE (conditions."time" >= COALESCE((_timescaledb_functions.cagg_watermark(3))::integer, '-2147483648'::integer)) + - | GROUP BY (public.time_bucket(24, conditions."time")); - -\x off -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+-------------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------- - 3 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "1008"} - 3 | 2 | NOT STARTED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 3 | 3 | NOT STARTED | DISABLE POLICIES | {"policies": null} - 3 | 4 | NOT STARTED | REFRESH NEW CAGG | {"window_start": "1008", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "integer"} - 3 | 5 | NOT STARTED | COPY DATA | {"end_ts": "100", "start_ts": "0", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 6 | NOT STARTED | COPY DATA | {"end_ts": "200", "start_ts": "100", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 7 | NOT STARTED | COPY DATA | {"end_ts": "300", "start_ts": "200", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 8 | NOT STARTED | COPY DATA | {"end_ts": "400", "start_ts": "300", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 9 | NOT STARTED | COPY DATA | {"end_ts": "500", "start_ts": "400", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 10 | NOT STARTED | COPY DATA | {"end_ts": "600", "start_ts": "500", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 11 | NOT STARTED | COPY DATA | {"end_ts": "700", "start_ts": "600", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 12 | NOT STARTED | COPY DATA | {"end_ts": "800", "start_ts": "700", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 13 | NOT STARTED | COPY DATA | {"end_ts": "900", "start_ts": "800", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 14 | NOT STARTED | COPY DATA | {"end_ts": "1000", "start_ts": "900", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 15 | NOT STARTED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 16 | NOT STARTED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 17 | NOT STARTED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 18 | NOT STARTED | ENABLE POLICIES | -(18 rows) - --- should resume the execution -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:169: WARNING: resuming the migration of the continuous aggregate "public.conditions_summary_daily" -psql:include/cagg_migrate_common.sql:169: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('1008' AS integer), NULL);" -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------- - 3 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "1008"} - 3 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 3 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 3 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "1008", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "integer"} - 3 | 5 | FINISHED | COPY DATA | {"end_ts": "100", "start_ts": "0", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 6 | FINISHED | COPY DATA | {"end_ts": "200", "start_ts": "100", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 7 | FINISHED | COPY DATA | {"end_ts": "300", "start_ts": "200", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 8 | FINISHED | COPY DATA | {"end_ts": "400", "start_ts": "300", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 9 | FINISHED | COPY DATA | {"end_ts": "500", "start_ts": "400", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 10 | FINISHED | COPY DATA | {"end_ts": "600", "start_ts": "500", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 11 | FINISHED | COPY DATA | {"end_ts": "700", "start_ts": "600", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 12 | FINISHED | COPY DATA | {"end_ts": "800", "start_ts": "700", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 13 | FINISHED | COPY DATA | {"end_ts": "900", "start_ts": "800", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 14 | FINISHED | COPY DATA | {"end_ts": "1000", "start_ts": "900", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 15 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 16 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 17 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 18 | FINISHED | ENABLE POLICIES | -(18 rows) - -\set ON_ERROR_STOP 0 --- should error because plan already exists -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:174: ERROR: plan already exists for materialized hypertable 3 -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:175: ERROR: plan already exists for continuous aggregate public.conditions_summary_daily -\set ON_ERROR_STOP 1 --- policies for test -ALTER MATERIALIZED VIEW conditions_summary_daily SET (timescaledb.compress=true); -psql:include/cagg_migrate_common.sql:179: NOTICE: defaulting compress_orderby to bucket -\if :IS_TIME_DIMENSION -SELECT add_retention_policy('conditions_summary_daily', '30 days'::interval); -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '30 days'::interval, '1 day'::interval, '1 hour'::interval); -SELECT add_compression_policy('conditions_summary_daily', '45 days'::interval); -\else -SELECT add_retention_policy('conditions_summary_daily', '400'::integer); - add_retention_policy ----------------------- - 1000 -(1 row) - -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '50'::integer, '1'::integer, '1 hour'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1001 -(1 row) - -SELECT add_compression_policy('conditions_summary_daily', '100'::integer); - add_compression_policy ------------------------- - 1002 -(1 row) - -\endif -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'MAT_SCHEMA_NAME' -AND hypertable_name = :'MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------+------------+---------------+-----------------------+----------------------------+------------------------+------------------------------------------- - 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 3, "compress_after": 100} | | | _timescaledb_internal | _materialized_hypertable_3 | _timescaledb_functions | policy_compression_check - 1001 | Refresh Continuous Aggregate Policy [1001] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 3} | | | _timescaledb_internal | _materialized_hypertable_3 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1000 | Retention Policy [1000] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": 400, "hypertable_id": 3} | | | _timescaledb_internal | _materialized_hypertable_3 | _timescaledb_functions | policy_retention_check -(3 rows) - --- execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:198: NOTICE: drop cascades to 10 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:199: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:200: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:200: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('1008' AS integer), NULL);" -SELECT - ca.raw_hypertable_id AS "NEW_RAW_HYPERTABLE_ID", - h.schema_name AS "NEW_MAT_SCHEMA_NAME", - h.table_name AS "NEW_MAT_TABLE_NAME", - partial_view_name AS "NEW_PART_VIEW_NAME", - partial_view_schema AS "NEW_PART_VIEW_SCHEMA", - direct_view_name AS "NEW_DIR_VIEW_NAME", - direct_view_schema AS "NEW_DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily_new' -\gset -\d+ conditions_summary_daily_new - View "public.conditions_summary_daily_new" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - bucket | integer | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_7.bucket, - _materialized_hypertable_7.min, - _materialized_hypertable_7.max, - _materialized_hypertable_7.avg, - _materialized_hypertable_7.sum - FROM _timescaledb_internal._materialized_hypertable_7 - WHERE _materialized_hypertable_7.bucket < COALESCE(_timescaledb_functions.cagg_watermark(7)::integer, '-2147483648'::integer) -UNION ALL - SELECT time_bucket(24, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.cagg_watermark(7)::integer, '-2147483648'::integer) - GROUP BY (time_bucket(24, conditions."time")); - -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'NEW_MAT_SCHEMA_NAME' -AND hypertable_name = :'NEW_MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------+------------+---------------+-----------------------+----------------------------+------------------------+------------------------------------------- - 1005 | Compression Policy [1005] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 7, "compress_after": 100} | | | _timescaledb_internal | _materialized_hypertable_7 | _timescaledb_functions | policy_compression_check - 1004 | Refresh Continuous Aggregate Policy [1004] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 7} | | | _timescaledb_internal | _materialized_hypertable_7 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1003 | Retention Policy [1003] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": 400, "hypertable_id": 7} | | | _timescaledb_internal | _materialized_hypertable_7 | _timescaledb_functions | policy_retention_check -(3 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------- - 3 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "1008"} - 3 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 3 | 3 | FINISHED | DISABLE POLICIES | {"policies": [1002, 1000]} - 3 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "1008", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "integer"} - 3 | 5 | FINISHED | COPY DATA | {"end_ts": "100", "start_ts": "0", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 6 | FINISHED | COPY DATA | {"end_ts": "200", "start_ts": "100", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 7 | FINISHED | COPY DATA | {"end_ts": "300", "start_ts": "200", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 8 | FINISHED | COPY DATA | {"end_ts": "400", "start_ts": "300", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 9 | FINISHED | COPY DATA | {"end_ts": "500", "start_ts": "400", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 10 | FINISHED | COPY DATA | {"end_ts": "600", "start_ts": "500", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 11 | FINISHED | COPY DATA | {"end_ts": "700", "start_ts": "600", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 12 | FINISHED | COPY DATA | {"end_ts": "800", "start_ts": "700", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 13 | FINISHED | COPY DATA | {"end_ts": "900", "start_ts": "800", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 14 | FINISHED | COPY DATA | {"end_ts": "1000", "start_ts": "900", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 3 | 15 | FINISHED | COPY POLICIES | {"policies": [1002, 1001, 1000], "cagg_name_new": "conditions_summary_daily_new"} - 3 | 16 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 17 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 3 | 18 | FINISHED | ENABLE POLICIES | {"policies": [1003, 1004, 1005, 1002, 1001, 1000]} -(18 rows) - --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - --- compress both caggs -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily') c ORDER BY c::regclass::text; - compress_chunk ------------------------------------------- - _timescaledb_internal._hyper_3_102_chunk - _timescaledb_internal._hyper_3_103_chunk - _timescaledb_internal._hyper_3_104_chunk - _timescaledb_internal._hyper_3_105_chunk - _timescaledb_internal._hyper_3_106_chunk - _timescaledb_internal._hyper_3_107_chunk - _timescaledb_internal._hyper_3_108_chunk - _timescaledb_internal._hyper_3_109_chunk - _timescaledb_internal._hyper_3_110_chunk - _timescaledb_internal._hyper_3_111_chunk -(10 rows) - -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily_new') c ORDER BY c::regclass::text; - compress_chunk ------------------------------------------- - _timescaledb_internal._hyper_7_128_chunk - _timescaledb_internal._hyper_7_129_chunk - _timescaledb_internal._hyper_7_130_chunk - _timescaledb_internal._hyper_7_131_chunk - _timescaledb_internal._hyper_7_132_chunk - _timescaledb_internal._hyper_7_133_chunk - _timescaledb_internal._hyper_7_134_chunk - _timescaledb_internal._hyper_7_135_chunk - _timescaledb_internal._hyper_7_136_chunk - _timescaledb_internal._hyper_7_137_chunk -(10 rows) - --- check migrated data after compression. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -CREATE OR REPLACE VIEW cagg_jobs AS -SELECT user_view_schema AS schema, user_view_name AS name, bgw_job.* -FROM _timescaledb_config.bgw_job -JOIN _timescaledb_catalog.continuous_agg ON mat_hypertable_id = hypertable_id -ORDER BY bgw_job.id; --- test migration overriding the new cagg and keeping the old -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:248: NOTICE: drop cascades to 10 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:249: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1000 | Retention Policy [1000] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 3 | {"drop_after": 400, "hypertable_id": 3} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1001 | Refresh Continuous Aggregate Policy [1001] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 3 | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 3} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 3 | {"hypertable_id": 3, "compress_after": 100} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE); -psql:include/cagg_migrate_common.sql:252: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:252: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('1008' AS integer), NULL);" --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - bucket | integer | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_9.bucket, - _materialized_hypertable_9.min, - _materialized_hypertable_9.max, - _materialized_hypertable_9.avg, - _materialized_hypertable_9.sum - 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(24, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.cagg_watermark(9)::integer, '-2147483648'::integer) - GROUP BY (time_bucket(24, conditions."time")); - --- cagg with the old format because it was overriden -\d+ conditions_summary_daily_old - View "public.conditions_summary_daily_old" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - bucket | integer | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_3.bucket, - _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_2_2, NULL::numeric) AS min, - _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_3_3, NULL::numeric) AS max, - _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_4_4, NULL::numeric) AS avg, - _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_3.agg_5_5, NULL::numeric) AS sum - FROM _timescaledb_internal._materialized_hypertable_3 - WHERE _materialized_hypertable_3.bucket < COALESCE(_timescaledb_functions.cagg_watermark(3)::integer, '-2147483648'::integer) - GROUP BY _materialized_hypertable_3.bucket -UNION ALL - SELECT time_bucket(24, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.cagg_watermark(3)::integer, '-2147483648'::integer) - GROUP BY (time_bucket(24, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:259: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1006 | Retention Policy [1006] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 9 | {"drop_after": 400, "hypertable_id": 9} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1007 | Refresh Continuous Aggregate Policy [1007] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 9 | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 9} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1008 | Compression Policy [1008] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 9 | {"hypertable_id": 9, "compress_after": 100} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return the old cagg jobs -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily_old | 1000 | Retention Policy [1000] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 3 | {"drop_after": 400, "hypertable_id": 3} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily_old | 1001 | Refresh Continuous Aggregate Policy [1001] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 3 | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 3} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily_old | 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 3 | {"hypertable_id": 3, "compress_after": 100} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- test migration overriding the new cagg and removing the old -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:269: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:270: NOTICE: drop cascades to 10 other objects -ALTER MATERIALIZED VIEW conditions_summary_daily_old RENAME TO conditions_summary_daily; --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1000 | Retention Policy [1000] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 3 | {"drop_after": 400, "hypertable_id": 3} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1001 | Refresh Continuous Aggregate Policy [1001] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 3 | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 3} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 3 | {"hypertable_id": 3, "compress_after": 100} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE, drop_old => TRUE); -psql:include/cagg_migrate_common.sql:274: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:274: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('1008' AS integer), NULL);" -psql:include/cagg_migrate_common.sql:274: NOTICE: drop cascades to 10 other objects -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1002 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1001 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1000 not found, skipping --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - bucket | integer | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_11.bucket, - _materialized_hypertable_11.min, - _materialized_hypertable_11.max, - _materialized_hypertable_11.avg, - _materialized_hypertable_11.sum - 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(24, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.cagg_watermark(11)::integer, '-2147483648'::integer) - GROUP BY (time_bucket(24, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:279: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 --- should fail because the old cagg was removed -SELECT * FROM conditions_summary_daily_old; -psql:include/cagg_migrate_common.sql:281: ERROR: relation "conditions_summary_daily_old" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+----------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1009 | Retention Policy [1009] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 11 | {"drop_after": 400, "hypertable_id": 11} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1010 | Refresh Continuous Aggregate Policy [1010] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 11 | {"end_offset": 1, "start_offset": 50, "mat_hypertable_id": 11} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1011 | Compression Policy [1011] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 11 | {"hypertable_id": 11, "compress_after": 100} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the old cagg was removed -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- permission tests -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:291: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -GRANT ALL ON TABLE conditions TO :ROLE_DEFAULT_PERM_USER; -ALTER MATERIALIZED VIEW conditions_summary_weekly OWNER TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:298: ERROR: permission denied for table continuous_agg_migrate_plan -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:308: ERROR: permission denied for table continuous_agg_migrate_plan_step -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan_step TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step_step_id_seq' catalog sequence -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:318: ERROR: permission denied for sequence continuous_agg_migrate_plan_step_step_id_seq -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; --- all necessary permissions granted -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:327: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_weekly_new', CAST('1008' AS integer), NULL);" --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_weekly -EXCEPT -SELECT * FROM conditions_summary_weekly_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------- - 4 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "1008"} - 4 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_weekly_new"} - 4 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 4 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "1008", "cagg_name_new": "conditions_summary_weekly_new", "window_start_type": "integer"} - 4 | 5 | FINISHED | COPY DATA | {"end_ts": "100", "start_ts": "0", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 6 | FINISHED | COPY DATA | {"end_ts": "200", "start_ts": "100", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 7 | FINISHED | COPY DATA | {"end_ts": "300", "start_ts": "200", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 8 | FINISHED | COPY DATA | {"end_ts": "400", "start_ts": "300", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 9 | FINISHED | COPY DATA | {"end_ts": "500", "start_ts": "400", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 10 | FINISHED | COPY DATA | {"end_ts": "600", "start_ts": "500", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 11 | FINISHED | COPY DATA | {"end_ts": "700", "start_ts": "600", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 12 | FINISHED | COPY DATA | {"end_ts": "800", "start_ts": "700", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 13 | FINISHED | COPY DATA | {"end_ts": "900", "start_ts": "800", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "integer"} - 4 | 14 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_weekly_new"} - 4 | 15 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 4 | 16 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 4 | 17 | FINISHED | ENABLE POLICIES | -(17 rows) - -RESET ROLE; --- according to the official documentation trying to execute a procedure with --- transaction control statements inside an explicit transaction should fail: --- https://www.postgresql.org/docs/current/sql-call.html --- `If CALL is executed in a transaction block, then the called procedure cannot --- execute transaction control statements. Transaction control statements are only --- allowed if CALL is executed in its own transaction.` -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:344: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_weekly_new; -psql:include/cagg_migrate_common.sql:345: NOTICE: drop cascades to 6 other objects -\set ON_ERROR_STOP 0 -BEGIN; --- should fail with `invalid transaction termination` -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:350: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 -CREATE FUNCTION execute_migration() RETURNS void AS -$$ -BEGIN - CALL cagg_migrate('conditions_summary_weekly'); - RETURN; -END; -$$ -LANGUAGE plpgsql; -\set ON_ERROR_STOP 0 --- execute migration inside a plpgsql function -BEGIN; --- should fail with `invalid transaction termination` -SELECT execute_migration(); -psql:include/cagg_migrate_common.sql:367: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 --- cleanup -DROP FUNCTION execute_migration(); -REVOKE SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan FROM :ROLE_DEFAULT_PERM_USER; -REVOKE USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq FROM :ROLE_DEFAULT_PERM_USER; -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:375: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:376: NOTICE: drop cascades to 10 other objects -DROP MATERIALIZED VIEW conditions_summary_weekly; -psql:include/cagg_migrate_common.sql:377: NOTICE: drop cascades to 6 other objects -DROP TABLE conditions; --- ######################################################## --- ## TIMESTAMP data type tests --- ######################################################## -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMP -\ir include/cagg_migrate_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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -CREATE TABLE conditions ( - "time" :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC -); -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_migrate_common.sql:20: WARNING: distributed hypertable is deprecated -psql:include/cagg_migrate_common.sql:20: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) - SELECT - generate_series('2022-01-01 00:00:00-00'::timestamptz, '2022-12-31 23:59:59-00'::timestamptz, '1 hour'), - 0.25; -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM public.conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM public.conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) - SELECT - generate_series(1, 1000, 1), - 0.25; -\endif --- new cagg format (finalized=true) -CREATE MATERIALIZED VIEW conditions_summary_daily_new -WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket -WITH NO DATA; --- older continuous aggregate to be migrated -CREATE MATERIALIZED VIEW conditions_summary_daily -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:95: NOTICE: refreshing continuous aggregate "conditions_summary_daily" --- for permission tests -CREATE MATERIALIZED VIEW conditions_summary_weekly -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 week', "time") AS bucket, -\else - time_bucket(INTEGER '168', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:113: NOTICE: refreshing continuous aggregate "conditions_summary_weekly" -\set ON_ERROR_STOP 0 --- should fail because we don't need to migrate finalized caggs -CALL cagg_migrate('conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:117: ERROR: continuous aggregate "public.conditions_summary_daily_new" does not require any migration -\set ON_ERROR_STOP 1 -\set ON_ERROR_STOP 0 --- should fail relation does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:122: ERROR: relation "conditions_summary_not_cagg" does not exist at character 19 -CREATE TABLE conditions_summary_not_cagg(); --- should fail continuous agg does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:125: ERROR: continuous aggregate "public.conditions_summary_not_cagg" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE conditions_summary_not_cagg; -SELECT - ca.raw_hypertable_id AS "RAW_HYPERTABLE_ID", - h.schema_name AS "MAT_SCHEMA_NAME", - h.table_name AS "MAT_TABLE_NAME", - partial_view_name AS "PART_VIEW_NAME", - partial_view_schema AS "PART_VIEW_SCHEMA", - direct_view_name AS "DIR_VIEW_NAME", - direct_view_schema AS "DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily' -\gset -\set ON_ERROR_STOP 0 --- should fail because the new cagg with suffix '_new' already exists -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:147: ERROR: continuous aggregate "public.conditions_summary_daily_new" already exists -\set ON_ERROR_STOP 1 --- remove the new cagg to execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; --- get and set all the cagg data -SELECT - _timescaledb_functions.cagg_migrate_pre_validation( - 'public', - 'conditions_summary_daily', - 'conditions_summary_daily_new' - ) AS "CAGG_DATA" -\gset -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -\x on -SELECT mat_hypertable_id, user_view_definition FROM _timescaledb_catalog.continuous_agg_migrate_plan; --[ RECORD 1 ]--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -mat_hypertable_id | 16 -user_view_definition | SELECT _materialized_hypertable_16.bucket, + - | _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_2_2, NULL::numeric) AS min, + - | _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_3_3, NULL::numeric) AS max, + - | _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_4_4, NULL::numeric) AS avg, + - | _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_5_5, NULL::numeric) AS sum + - | FROM _timescaledb_internal._materialized_hypertable_16 + - | WHERE (_materialized_hypertable_16.bucket < COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(16)), '-infinity'::timestamp without time zone))+ - | GROUP BY _materialized_hypertable_16.bucket + - | UNION ALL + - | SELECT public.time_bucket('@ 1 day'::interval, conditions."time") AS bucket, + - | min(conditions.temperature) AS min, + - | max(conditions.temperature) AS max, + - | avg(conditions.temperature) AS avg, + - | sum(conditions.temperature) AS sum + - | FROM public.conditions + - | WHERE (conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(16)), '-infinity'::timestamp without time zone)) + - | GROUP BY (public.time_bucket('@ 1 day'::interval, conditions."time")); - -\x off -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+-------------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 16 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 16 | 2 | NOT STARTED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 16 | 3 | NOT STARTED | DISABLE POLICIES | {"policies": null} - 16 | 4 | NOT STARTED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp without time zone"} - 16 | 5 | NOT STARTED | COPY DATA | {"end_ts": "Fri Mar 11 00:00:00 2022", "start_ts": "Fri Dec 31 00:00:00 2021", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 6 | NOT STARTED | COPY DATA | {"end_ts": "Fri May 20 00:00:00 2022", "start_ts": "Fri Mar 11 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 7 | NOT STARTED | COPY DATA | {"end_ts": "Fri Jul 29 00:00:00 2022", "start_ts": "Fri May 20 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 8 | NOT STARTED | COPY DATA | {"end_ts": "Fri Oct 07 00:00:00 2022", "start_ts": "Fri Jul 29 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 9 | NOT STARTED | COPY DATA | {"end_ts": "Fri Dec 16 00:00:00 2022", "start_ts": "Fri Oct 07 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 10 | NOT STARTED | COPY DATA | {"end_ts": "Fri Feb 24 00:00:00 2023", "start_ts": "Fri Dec 16 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 11 | NOT STARTED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 12 | NOT STARTED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 13 | NOT STARTED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 14 | NOT STARTED | ENABLE POLICIES | -(14 rows) - --- should resume the execution -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:169: WARNING: resuming the migration of the continuous aggregate "public.conditions_summary_daily" -psql:include/cagg_migrate_common.sql:169: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('Sun Jan 01 00:00:00 2023' AS timestamp without time zone), NULL);" -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 16 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 16 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 16 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 16 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp without time zone"} - 16 | 5 | FINISHED | COPY DATA | {"end_ts": "Fri Mar 11 00:00:00 2022", "start_ts": "Fri Dec 31 00:00:00 2021", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 6 | FINISHED | COPY DATA | {"end_ts": "Fri May 20 00:00:00 2022", "start_ts": "Fri Mar 11 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 7 | FINISHED | COPY DATA | {"end_ts": "Fri Jul 29 00:00:00 2022", "start_ts": "Fri May 20 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 8 | FINISHED | COPY DATA | {"end_ts": "Fri Oct 07 00:00:00 2022", "start_ts": "Fri Jul 29 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 9 | FINISHED | COPY DATA | {"end_ts": "Fri Dec 16 00:00:00 2022", "start_ts": "Fri Oct 07 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 10 | FINISHED | COPY DATA | {"end_ts": "Fri Feb 24 00:00:00 2023", "start_ts": "Fri Dec 16 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 11 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 14 | FINISHED | ENABLE POLICIES | -(14 rows) - -\set ON_ERROR_STOP 0 --- should error because plan already exists -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:174: ERROR: plan already exists for materialized hypertable 16 -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:175: ERROR: plan already exists for continuous aggregate public.conditions_summary_daily -\set ON_ERROR_STOP 1 --- policies for test -ALTER MATERIALIZED VIEW conditions_summary_daily SET (timescaledb.compress=true); -psql:include/cagg_migrate_common.sql:179: NOTICE: defaulting compress_orderby to bucket -\if :IS_TIME_DIMENSION -SELECT add_retention_policy('conditions_summary_daily', '30 days'::interval); - add_retention_policy ----------------------- - 1012 -(1 row) - -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '30 days'::interval, '1 day'::interval, '1 hour'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1013 -(1 row) - -SELECT add_compression_policy('conditions_summary_daily', '45 days'::interval); - add_compression_policy ------------------------- - 1014 -(1 row) - -\else -SELECT add_retention_policy('conditions_summary_daily', '400'::integer); -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '50'::integer, '1'::integer, '1 hour'::interval); -SELECT add_compression_policy('conditions_summary_daily', '100'::integer); -\endif -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'MAT_SCHEMA_NAME' -AND hypertable_name = :'MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------------------------+------------+---------------+-----------------------+-----------------------------+------------------------+------------------------------------------- - 1014 | Compression Policy [1014] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 16, "compress_after": "@ 45 days"} | | | _timescaledb_internal | _materialized_hypertable_16 | _timescaledb_functions | policy_compression_check - 1013 | Refresh Continuous Aggregate Policy [1013] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 16} | | | _timescaledb_internal | _materialized_hypertable_16 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1012 | Retention Policy [1012] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": "@ 30 days", "hypertable_id": 16} | | | _timescaledb_internal | _materialized_hypertable_16 | _timescaledb_functions | policy_retention_check -(3 rows) - --- execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:198: NOTICE: drop cascades to 6 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:199: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:200: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:200: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('Sun Jan 01 00:00:00 2023' AS timestamp without time zone), NULL);" -SELECT - ca.raw_hypertable_id AS "NEW_RAW_HYPERTABLE_ID", - h.schema_name AS "NEW_MAT_SCHEMA_NAME", - h.table_name AS "NEW_MAT_TABLE_NAME", - partial_view_name AS "NEW_PART_VIEW_NAME", - partial_view_schema AS "NEW_PART_VIEW_SCHEMA", - direct_view_name AS "NEW_DIR_VIEW_NAME", - direct_view_schema AS "NEW_DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily_new' -\gset -\d+ conditions_summary_daily_new - View "public.conditions_summary_daily_new" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+-----------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp without time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_20.bucket, - _materialized_hypertable_20.min, - _materialized_hypertable_20.max, - _materialized_hypertable_20.avg, - _materialized_hypertable_20.sum - FROM _timescaledb_internal._materialized_hypertable_20 - WHERE _materialized_hypertable_20.bucket < COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(20)), '-infinity'::timestamp without time zone) -UNION ALL - SELECT time_bucket('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(20)), '-infinity'::timestamp without time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'NEW_MAT_SCHEMA_NAME' -AND hypertable_name = :'NEW_MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------------------------+------------+---------------+-----------------------+-----------------------------+------------------------+------------------------------------------- - 1017 | Compression Policy [1017] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 20, "compress_after": "@ 45 days"} | | | _timescaledb_internal | _materialized_hypertable_20 | _timescaledb_functions | policy_compression_check - 1016 | Refresh Continuous Aggregate Policy [1016] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 20} | | | _timescaledb_internal | _materialized_hypertable_20 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1015 | Retention Policy [1015] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": "@ 30 days", "hypertable_id": 20} | | | _timescaledb_internal | _materialized_hypertable_20 | _timescaledb_functions | policy_retention_check -(3 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 16 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 16 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 16 | 3 | FINISHED | DISABLE POLICIES | {"policies": [1014, 1012]} - 16 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp without time zone"} - 16 | 5 | FINISHED | COPY DATA | {"end_ts": "Fri Mar 11 00:00:00 2022", "start_ts": "Fri Dec 31 00:00:00 2021", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 6 | FINISHED | COPY DATA | {"end_ts": "Fri May 20 00:00:00 2022", "start_ts": "Fri Mar 11 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 7 | FINISHED | COPY DATA | {"end_ts": "Fri Jul 29 00:00:00 2022", "start_ts": "Fri May 20 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 8 | FINISHED | COPY DATA | {"end_ts": "Fri Oct 07 00:00:00 2022", "start_ts": "Fri Jul 29 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 9 | FINISHED | COPY DATA | {"end_ts": "Fri Dec 16 00:00:00 2022", "start_ts": "Fri Oct 07 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 10 | FINISHED | COPY DATA | {"end_ts": "Fri Feb 24 00:00:00 2023", "start_ts": "Fri Dec 16 00:00:00 2022", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 16 | 11 | FINISHED | COPY POLICIES | {"policies": [1014, 1013, 1012], "cagg_name_new": "conditions_summary_daily_new"} - 16 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 16 | 14 | FINISHED | ENABLE POLICIES | {"policies": [1015, 1016, 1017, 1014, 1013, 1012]} -(14 rows) - --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - --- compress both caggs -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily') c ORDER BY c::regclass::text; - compress_chunk -------------------------------------------- - _timescaledb_internal._hyper_16_237_chunk - _timescaledb_internal._hyper_16_238_chunk - _timescaledb_internal._hyper_16_239_chunk - _timescaledb_internal._hyper_16_240_chunk - _timescaledb_internal._hyper_16_241_chunk - _timescaledb_internal._hyper_16_242_chunk -(6 rows) - -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily_new') c ORDER BY c::regclass::text; - compress_chunk -------------------------------------------- - _timescaledb_internal._hyper_20_255_chunk - _timescaledb_internal._hyper_20_256_chunk - _timescaledb_internal._hyper_20_257_chunk - _timescaledb_internal._hyper_20_258_chunk - _timescaledb_internal._hyper_20_259_chunk - _timescaledb_internal._hyper_20_260_chunk -(6 rows) - --- check migrated data after compression. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -CREATE OR REPLACE VIEW cagg_jobs AS -SELECT user_view_schema AS schema, user_view_name AS name, bgw_job.* -FROM _timescaledb_config.bgw_job -JOIN _timescaledb_catalog.continuous_agg ON mat_hypertable_id = hypertable_id -ORDER BY bgw_job.id; --- test migration overriding the new cagg and keeping the old -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:248: NOTICE: drop cascades to 6 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:249: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1012 | Retention Policy [1012] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 16 | {"drop_after": "@ 30 days", "hypertable_id": 16} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1013 | Refresh Continuous Aggregate Policy [1013] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 16 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 16} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1014 | Compression Policy [1014] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 16 | {"hypertable_id": 16, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE); -psql:include/cagg_migrate_common.sql:252: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:252: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('Sun Jan 01 00:00:00 2023' AS timestamp without time zone), NULL);" --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+-----------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp without time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_22.bucket, - _materialized_hypertable_22.min, - _materialized_hypertable_22.max, - _materialized_hypertable_22.avg, - _materialized_hypertable_22.sum - 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('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - 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('@ 1 day'::interval, conditions."time")); - --- cagg with the old format because it was overriden -\d+ conditions_summary_daily_old - View "public.conditions_summary_daily_old" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+-----------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp without time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_16.bucket, - _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_2_2, NULL::numeric) AS min, - _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_3_3, NULL::numeric) AS max, - _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_4_4, NULL::numeric) AS avg, - _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_16.agg_5_5, NULL::numeric) AS sum - FROM _timescaledb_internal._materialized_hypertable_16 - WHERE _materialized_hypertable_16.bucket < COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(16)), '-infinity'::timestamp without time zone) - GROUP BY _materialized_hypertable_16.bucket -UNION ALL - SELECT time_bucket('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(16)), '-infinity'::timestamp without time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:259: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1018 | Retention Policy [1018] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 22 | {"drop_after": "@ 30 days", "hypertable_id": 22} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1019 | Refresh Continuous Aggregate Policy [1019] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 22 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 22} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1020 | Compression Policy [1020] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 22 | {"hypertable_id": 22, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return the old cagg jobs -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily_old | 1012 | Retention Policy [1012] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 16 | {"drop_after": "@ 30 days", "hypertable_id": 16} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily_old | 1013 | Refresh Continuous Aggregate Policy [1013] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 16 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 16} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily_old | 1014 | Compression Policy [1014] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 16 | {"hypertable_id": 16, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- test migration overriding the new cagg and removing the old -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:269: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:270: NOTICE: drop cascades to 6 other objects -ALTER MATERIALIZED VIEW conditions_summary_daily_old RENAME TO conditions_summary_daily; --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1012 | Retention Policy [1012] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 16 | {"drop_after": "@ 30 days", "hypertable_id": 16} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1013 | Refresh Continuous Aggregate Policy [1013] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 16 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 16} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1014 | Compression Policy [1014] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 16 | {"hypertable_id": 16, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE, drop_old => TRUE); -psql:include/cagg_migrate_common.sql:274: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:274: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('Sun Jan 01 00:00:00 2023' AS timestamp without time zone), NULL);" -psql:include/cagg_migrate_common.sql:274: NOTICE: drop cascades to 6 other objects -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1014 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1013 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1012 not found, skipping --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+-----------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp without time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_24.bucket, - _materialized_hypertable_24.min, - _materialized_hypertable_24.max, - _materialized_hypertable_24.avg, - _materialized_hypertable_24.sum - 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 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp_without_timezone(_timescaledb_functions.cagg_watermark(24)), '-infinity'::timestamp without time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:279: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 --- should fail because the old cagg was removed -SELECT * FROM conditions_summary_daily_old; -psql:include/cagg_migrate_common.sql:281: ERROR: relation "conditions_summary_daily_old" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1021 | Retention Policy [1021] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 24 | {"drop_after": "@ 30 days", "hypertable_id": 24} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1022 | Refresh Continuous Aggregate Policy [1022] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 24 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 24} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1023 | Compression Policy [1023] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 24 | {"hypertable_id": 24, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the old cagg was removed -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- permission tests -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:291: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -GRANT ALL ON TABLE conditions TO :ROLE_DEFAULT_PERM_USER; -ALTER MATERIALIZED VIEW conditions_summary_weekly OWNER TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:298: ERROR: permission denied for table continuous_agg_migrate_plan -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:308: ERROR: permission denied for sequence continuous_agg_migrate_plan_step_step_id_seq -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan_step TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step_step_id_seq' catalog sequence -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:318: ERROR: permission denied for sequence continuous_agg_migrate_plan_step_step_id_seq -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; --- all necessary permissions granted -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:327: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_weekly_new', CAST('Mon Jan 02 00:00:00 2023' AS timestamp without time zone), NULL);" --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_weekly -EXCEPT -SELECT * FROM conditions_summary_weekly_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 17 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Mon Jan 02 00:00:00 2023"} - 17 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_weekly_new"} - 17 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 17 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Mon Jan 02 00:00:00 2023", "cagg_name_new": "conditions_summary_weekly_new", "window_start_type": "timestamp without time zone"} - 17 | 5 | FINISHED | COPY DATA | {"end_ts": "Mon Mar 07 00:00:00 2022", "start_ts": "Mon Dec 27 00:00:00 2021", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 6 | FINISHED | COPY DATA | {"end_ts": "Mon May 16 00:00:00 2022", "start_ts": "Mon Mar 07 00:00:00 2022", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 7 | FINISHED | COPY DATA | {"end_ts": "Mon Jul 25 00:00:00 2022", "start_ts": "Mon May 16 00:00:00 2022", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 8 | FINISHED | COPY DATA | {"end_ts": "Mon Oct 03 00:00:00 2022", "start_ts": "Mon Jul 25 00:00:00 2022", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 9 | FINISHED | COPY DATA | {"end_ts": "Mon Dec 12 00:00:00 2022", "start_ts": "Mon Oct 03 00:00:00 2022", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 10 | FINISHED | COPY DATA | {"end_ts": "Mon Feb 20 00:00:00 2023", "start_ts": "Mon Dec 12 00:00:00 2022", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp without time zone"} - 17 | 11 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_weekly_new"} - 17 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 17 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 17 | 14 | FINISHED | ENABLE POLICIES | -(14 rows) - -RESET ROLE; --- according to the official documentation trying to execute a procedure with --- transaction control statements inside an explicit transaction should fail: --- https://www.postgresql.org/docs/current/sql-call.html --- `If CALL is executed in a transaction block, then the called procedure cannot --- execute transaction control statements. Transaction control statements are only --- allowed if CALL is executed in its own transaction.` -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:344: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_weekly_new; -psql:include/cagg_migrate_common.sql:345: NOTICE: drop cascades to 6 other objects -\set ON_ERROR_STOP 0 -BEGIN; --- should fail with `invalid transaction termination` -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:350: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 -CREATE FUNCTION execute_migration() RETURNS void AS -$$ -BEGIN - CALL cagg_migrate('conditions_summary_weekly'); - RETURN; -END; -$$ -LANGUAGE plpgsql; -\set ON_ERROR_STOP 0 --- execute migration inside a plpgsql function -BEGIN; --- should fail with `invalid transaction termination` -SELECT execute_migration(); -psql:include/cagg_migrate_common.sql:367: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 --- cleanup -DROP FUNCTION execute_migration(); -REVOKE SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan FROM :ROLE_DEFAULT_PERM_USER; -REVOKE USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq FROM :ROLE_DEFAULT_PERM_USER; -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:375: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:376: NOTICE: drop cascades to 6 other objects -DROP MATERIALIZED VIEW conditions_summary_weekly; -psql:include/cagg_migrate_common.sql:377: NOTICE: drop cascades to 6 other objects -DROP TABLE conditions; --- ######################################################## --- ## TIMESTAMPTZ data type tests --- ######################################################## -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\ir include/cagg_migrate_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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -CREATE TABLE conditions ( - "time" :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC -); -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_migrate_common.sql:20: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature) - SELECT - generate_series('2022-01-01 00:00:00-00'::timestamptz, '2022-12-31 23:59:59-00'::timestamptz, '1 hour'), - 0.25; -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM public.conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM public.conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature) - SELECT - generate_series(1, 1000, 1), - 0.25; -\endif --- new cagg format (finalized=true) -CREATE MATERIALIZED VIEW conditions_summary_daily_new -WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket -WITH NO DATA; --- older continuous aggregate to be migrated -CREATE MATERIALIZED VIEW conditions_summary_daily -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 day', "time") AS bucket, -\else - time_bucket(INTEGER '24', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:95: NOTICE: refreshing continuous aggregate "conditions_summary_daily" --- for permission tests -CREATE MATERIALIZED VIEW conditions_summary_weekly -WITH (timescaledb.continuous, timescaledb.materialized_only=false, timescaledb.finalized=false) AS -SELECT -\if :IS_TIME_DIMENSION - time_bucket(INTERVAL '1 week', "time") AS bucket, -\else - time_bucket(INTEGER '168', "time") AS bucket, -\endif - MIN(temperature), - MAX(temperature), - AVG(temperature), - SUM(temperature) -FROM - conditions -GROUP BY - bucket; -psql:include/cagg_migrate_common.sql:113: NOTICE: refreshing continuous aggregate "conditions_summary_weekly" -\set ON_ERROR_STOP 0 --- should fail because we don't need to migrate finalized caggs -CALL cagg_migrate('conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:117: ERROR: continuous aggregate "public.conditions_summary_daily_new" does not require any migration -\set ON_ERROR_STOP 1 -\set ON_ERROR_STOP 0 --- should fail relation does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:122: ERROR: relation "conditions_summary_not_cagg" does not exist at character 19 -CREATE TABLE conditions_summary_not_cagg(); --- should fail continuous agg does not exist -CALL cagg_migrate('conditions_summary_not_cagg'); -psql:include/cagg_migrate_common.sql:125: ERROR: continuous aggregate "public.conditions_summary_not_cagg" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE conditions_summary_not_cagg; -SELECT - ca.raw_hypertable_id AS "RAW_HYPERTABLE_ID", - h.schema_name AS "MAT_SCHEMA_NAME", - h.table_name AS "MAT_TABLE_NAME", - partial_view_name AS "PART_VIEW_NAME", - partial_view_schema AS "PART_VIEW_SCHEMA", - direct_view_name AS "DIR_VIEW_NAME", - direct_view_schema AS "DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily' -\gset -\set ON_ERROR_STOP 0 --- should fail because the new cagg with suffix '_new' already exists -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:147: ERROR: continuous aggregate "public.conditions_summary_daily_new" already exists -\set ON_ERROR_STOP 1 --- remove the new cagg to execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; --- get and set all the cagg data -SELECT - _timescaledb_functions.cagg_migrate_pre_validation( - 'public', - 'conditions_summary_daily', - 'conditions_summary_daily_new' - ) AS "CAGG_DATA" -\gset -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -\x on -SELECT mat_hypertable_id, user_view_definition FROM _timescaledb_catalog.continuous_agg_migrate_plan; --[ RECORD 1 ]--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -mat_hypertable_id | 29 -user_view_definition | SELECT _materialized_hypertable_29.bucket, + - | _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_2_2, NULL::numeric) AS min,+ - | _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_3_3, NULL::numeric) AS max,+ - | _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_4_4, NULL::numeric) AS avg,+ - | _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_5_5, NULL::numeric) AS sum + - | FROM _timescaledb_internal._materialized_hypertable_29 + - | WHERE (_materialized_hypertable_29.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(29)), '-infinity'::timestamp with time zone)) + - | GROUP BY _materialized_hypertable_29.bucket + - | UNION ALL + - | SELECT public.time_bucket('@ 1 day'::interval, conditions."time") AS bucket, + - | min(conditions.temperature) AS min, + - | max(conditions.temperature) AS max, + - | avg(conditions.temperature) AS avg, + - | sum(conditions.temperature) AS sum + - | FROM public.conditions + - | WHERE (conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(29)), '-infinity'::timestamp with time zone)) + - | GROUP BY (public.time_bucket('@ 1 day'::interval, conditions."time")); - -\x off -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+-------------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 29 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 29 | 2 | NOT STARTED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 29 | 3 | NOT STARTED | DISABLE POLICIES | {"policies": null} - 29 | 4 | NOT STARTED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp with time zone"} - 29 | 5 | NOT STARTED | COPY DATA | {"end_ts": "Fri Mar 11 16:00:00 2022 PST", "start_ts": "Fri Dec 31 16:00:00 2021 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 6 | NOT STARTED | COPY DATA | {"end_ts": "Fri May 20 16:00:00 2022 PDT", "start_ts": "Fri Mar 11 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 7 | NOT STARTED | COPY DATA | {"end_ts": "Fri Jul 29 16:00:00 2022 PDT", "start_ts": "Fri May 20 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 8 | NOT STARTED | COPY DATA | {"end_ts": "Fri Oct 07 16:00:00 2022 PDT", "start_ts": "Fri Jul 29 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 9 | NOT STARTED | COPY DATA | {"end_ts": "Fri Dec 16 16:00:00 2022 PST", "start_ts": "Fri Oct 07 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 10 | NOT STARTED | COPY DATA | {"end_ts": "Fri Feb 24 16:00:00 2023 PST", "start_ts": "Fri Dec 16 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 11 | NOT STARTED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 12 | NOT STARTED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 13 | NOT STARTED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 14 | NOT STARTED | ENABLE POLICIES | -(14 rows) - --- should resume the execution -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:169: WARNING: resuming the migration of the continuous aggregate "public.conditions_summary_daily" -psql:include/cagg_migrate_common.sql:169: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('Sun Jan 01 00:00:00 2023' AS timestamp with time zone), NULL);" -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 29 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 29 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 29 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 29 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp with time zone"} - 29 | 5 | FINISHED | COPY DATA | {"end_ts": "Fri Mar 11 16:00:00 2022 PST", "start_ts": "Fri Dec 31 16:00:00 2021 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 6 | FINISHED | COPY DATA | {"end_ts": "Fri May 20 16:00:00 2022 PDT", "start_ts": "Fri Mar 11 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 7 | FINISHED | COPY DATA | {"end_ts": "Fri Jul 29 16:00:00 2022 PDT", "start_ts": "Fri May 20 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 8 | FINISHED | COPY DATA | {"end_ts": "Fri Oct 07 16:00:00 2022 PDT", "start_ts": "Fri Jul 29 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 9 | FINISHED | COPY DATA | {"end_ts": "Fri Dec 16 16:00:00 2022 PST", "start_ts": "Fri Oct 07 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 10 | FINISHED | COPY DATA | {"end_ts": "Fri Feb 24 16:00:00 2023 PST", "start_ts": "Fri Dec 16 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 11 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 14 | FINISHED | ENABLE POLICIES | -(14 rows) - -\set ON_ERROR_STOP 0 --- should error because plan already exists -CALL _timescaledb_functions.cagg_migrate_create_plan(:'CAGG_DATA', 'conditions_summary_daily_new'); -psql:include/cagg_migrate_common.sql:174: ERROR: plan already exists for materialized hypertable 29 -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:175: ERROR: plan already exists for continuous aggregate public.conditions_summary_daily -\set ON_ERROR_STOP 1 --- policies for test -ALTER MATERIALIZED VIEW conditions_summary_daily SET (timescaledb.compress=true); -psql:include/cagg_migrate_common.sql:179: NOTICE: defaulting compress_orderby to bucket -\if :IS_TIME_DIMENSION -SELECT add_retention_policy('conditions_summary_daily', '30 days'::interval); - add_retention_policy ----------------------- - 1024 -(1 row) - -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '30 days'::interval, '1 day'::interval, '1 hour'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1025 -(1 row) - -SELECT add_compression_policy('conditions_summary_daily', '45 days'::interval); - add_compression_policy ------------------------- - 1026 -(1 row) - -\else -SELECT add_retention_policy('conditions_summary_daily', '400'::integer); -SELECT add_continuous_aggregate_policy('conditions_summary_daily', '50'::integer, '1'::integer, '1 hour'::interval); -SELECT add_compression_policy('conditions_summary_daily', '100'::integer); -\endif -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'MAT_SCHEMA_NAME' -AND hypertable_name = :'MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------------------------+------------+---------------+-----------------------+-----------------------------+------------------------+------------------------------------------- - 1026 | Compression Policy [1026] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 29, "compress_after": "@ 45 days"} | | | _timescaledb_internal | _materialized_hypertable_29 | _timescaledb_functions | policy_compression_check - 1025 | Refresh Continuous Aggregate Policy [1025] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 29} | | | _timescaledb_internal | _materialized_hypertable_29 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1024 | Retention Policy [1024] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": "@ 30 days", "hypertable_id": 29} | | | _timescaledb_internal | _materialized_hypertable_29 | _timescaledb_functions | policy_retention_check -(3 rows) - --- execute the migration -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:198: NOTICE: drop cascades to 6 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:199: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -CALL cagg_migrate('conditions_summary_daily'); -psql:include/cagg_migrate_common.sql:200: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:200: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily_new', CAST('Sun Jan 01 00:00:00 2023' AS timestamp with time zone), NULL);" -SELECT - ca.raw_hypertable_id AS "NEW_RAW_HYPERTABLE_ID", - h.schema_name AS "NEW_MAT_SCHEMA_NAME", - h.table_name AS "NEW_MAT_TABLE_NAME", - partial_view_name AS "NEW_PART_VIEW_NAME", - partial_view_schema AS "NEW_PART_VIEW_SCHEMA", - direct_view_name AS "NEW_DIR_VIEW_NAME", - direct_view_schema AS "NEW_DIR_VIEW_SCHEMA" -FROM - _timescaledb_catalog.continuous_agg ca - JOIN _timescaledb_catalog.hypertable h ON (h.id = ca.mat_hypertable_id) -WHERE - user_view_name = 'conditions_summary_daily_new' -\gset -\d+ conditions_summary_daily_new - View "public.conditions_summary_daily_new" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_33.bucket, - _materialized_hypertable_33.min, - _materialized_hypertable_33.max, - _materialized_hypertable_33.avg, - _materialized_hypertable_33.sum - FROM _timescaledb_internal._materialized_hypertable_33 - WHERE _materialized_hypertable_33.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(33)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(33)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -SELECT * -FROM timescaledb_information.jobs -WHERE hypertable_schema = :'NEW_MAT_SCHEMA_NAME' -AND hypertable_name = :'NEW_MAT_TABLE_NAME' -AND job_id >= 1000; - job_id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | config | next_start | initial_start | hypertable_schema | hypertable_name | check_schema | check_name ---------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------------------------------------------------------------------------+------------+---------------+-----------------------+-----------------------------+------------------------+------------------------------------------- - 1029 | Compression Policy [1029] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | {"hypertable_id": 33, "compress_after": "@ 45 days"} | | | _timescaledb_internal | _materialized_hypertable_33 | _timescaledb_functions | policy_compression_check - 1028 | Refresh Continuous Aggregate Policy [1028] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 33} | | | _timescaledb_internal | _materialized_hypertable_33 | _timescaledb_functions | policy_refresh_continuous_aggregate_check - 1027 | Retention Policy [1027] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | {"drop_after": "@ 30 days", "hypertable_id": 33} | | | _timescaledb_internal | _materialized_hypertable_33 | _timescaledb_functions | policy_retention_check -(3 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 29 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Sun Jan 01 00:00:00 2023"} - 29 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_daily_new"} - 29 | 3 | FINISHED | DISABLE POLICIES | {"policies": [1026, 1024]} - 29 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Sun Jan 01 00:00:00 2023", "cagg_name_new": "conditions_summary_daily_new", "window_start_type": "timestamp with time zone"} - 29 | 5 | FINISHED | COPY DATA | {"end_ts": "Fri Mar 11 16:00:00 2022 PST", "start_ts": "Fri Dec 31 16:00:00 2021 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 6 | FINISHED | COPY DATA | {"end_ts": "Fri May 20 16:00:00 2022 PDT", "start_ts": "Fri Mar 11 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 7 | FINISHED | COPY DATA | {"end_ts": "Fri Jul 29 16:00:00 2022 PDT", "start_ts": "Fri May 20 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 8 | FINISHED | COPY DATA | {"end_ts": "Fri Oct 07 16:00:00 2022 PDT", "start_ts": "Fri Jul 29 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 9 | FINISHED | COPY DATA | {"end_ts": "Fri Dec 16 16:00:00 2022 PST", "start_ts": "Fri Oct 07 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 10 | FINISHED | COPY DATA | {"end_ts": "Fri Feb 24 16:00:00 2023 PST", "start_ts": "Fri Dec 16 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_daily_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 29 | 11 | FINISHED | COPY POLICIES | {"policies": [1026, 1025, 1024], "cagg_name_new": "conditions_summary_daily_new"} - 29 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_daily_new"} - 29 | 14 | FINISHED | ENABLE POLICIES | {"policies": [1027, 1028, 1029, 1026, 1025, 1024]} -(14 rows) - --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - --- compress both caggs -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily') c ORDER BY c::regclass::text; - compress_chunk -------------------------------------------- - _timescaledb_internal._hyper_29_344_chunk - _timescaledb_internal._hyper_29_345_chunk - _timescaledb_internal._hyper_29_346_chunk - _timescaledb_internal._hyper_29_347_chunk - _timescaledb_internal._hyper_29_348_chunk - _timescaledb_internal._hyper_29_349_chunk -(6 rows) - -SELECT compress_chunk(c) FROM show_chunks('conditions_summary_daily_new') c ORDER BY c::regclass::text; - compress_chunk -------------------------------------------- - _timescaledb_internal._hyper_33_362_chunk - _timescaledb_internal._hyper_33_363_chunk - _timescaledb_internal._hyper_33_364_chunk - _timescaledb_internal._hyper_33_365_chunk - _timescaledb_internal._hyper_33_366_chunk - _timescaledb_internal._hyper_33_367_chunk -(6 rows) - --- check migrated data after compression. should return 0 (zero) rows -SELECT * FROM conditions_summary_daily -EXCEPT -SELECT * FROM conditions_summary_daily_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -CREATE OR REPLACE VIEW cagg_jobs AS -SELECT user_view_schema AS schema, user_view_name AS name, bgw_job.* -FROM _timescaledb_config.bgw_job -JOIN _timescaledb_catalog.continuous_agg ON mat_hypertable_id = hypertable_id -ORDER BY bgw_job.id; --- test migration overriding the new cagg and keeping the old -DROP MATERIALIZED VIEW conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:248: NOTICE: drop cascades to 6 other objects -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:249: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1024 | Retention Policy [1024] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 29 | {"drop_after": "@ 30 days", "hypertable_id": 29} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1025 | Refresh Continuous Aggregate Policy [1025] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 29 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 29} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1026 | Compression Policy [1026] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 29 | {"hypertable_id": 29, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE); -psql:include/cagg_migrate_common.sql:252: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:252: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('Sun Jan 01 00:00:00 2023' AS timestamp with time zone), NULL);" --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_35.bucket, - _materialized_hypertable_35.min, - _materialized_hypertable_35.max, - _materialized_hypertable_35.avg, - _materialized_hypertable_35.sum - 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('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(35)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - --- cagg with the old format because it was overriden -\d+ conditions_summary_daily_old - View "public.conditions_summary_daily_old" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_29.bucket, - _timescaledb_functions.finalize_agg('pg_catalog.min(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_2_2, NULL::numeric) AS min, - _timescaledb_functions.finalize_agg('pg_catalog.max(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_3_3, NULL::numeric) AS max, - _timescaledb_functions.finalize_agg('pg_catalog.avg(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_4_4, NULL::numeric) AS avg, - _timescaledb_functions.finalize_agg('pg_catalog.sum(numeric)'::text, NULL::name, NULL::name, '{{pg_catalog,numeric}}'::name[], _materialized_hypertable_29.agg_5_5, NULL::numeric) AS sum - FROM _timescaledb_internal._materialized_hypertable_29 - WHERE _materialized_hypertable_29.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(29)), '-infinity'::timestamp with time zone) - GROUP BY _materialized_hypertable_29.bucket -UNION ALL - SELECT time_bucket('@ 1 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(29)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:259: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1030 | Retention Policy [1030] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 35 | {"drop_after": "@ 30 days", "hypertable_id": 35} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1031 | Refresh Continuous Aggregate Policy [1031] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 35 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 35} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1032 | Compression Policy [1032] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 35 | {"hypertable_id": 35, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return the old cagg jobs -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily_old | 1024 | Retention Policy [1024] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 29 | {"drop_after": "@ 30 days", "hypertable_id": 29} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily_old | 1025 | Refresh Continuous Aggregate Policy [1025] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 29 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 29} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily_old | 1026 | Compression Policy [1026] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 29 | {"hypertable_id": 29, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- test migration overriding the new cagg and removing the old -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:269: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:270: NOTICE: drop cascades to 6 other objects -ALTER MATERIALIZED VIEW conditions_summary_daily_old RENAME TO conditions_summary_daily; --- check policies before the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1024 | Retention Policy [1024] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 29 | {"drop_after": "@ 30 days", "hypertable_id": 29} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1025 | Refresh Continuous Aggregate Policy [1025] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 29 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 29} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1026 | Compression Policy [1026] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 29 | {"hypertable_id": 29, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - -CALL cagg_migrate('conditions_summary_daily', override => TRUE, drop_old => TRUE); -psql:include/cagg_migrate_common.sql:274: NOTICE: defaulting compress_orderby to bucket -psql:include/cagg_migrate_common.sql:274: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_daily', CAST('Sun Jan 01 00:00:00 2023' AS timestamp with time zone), NULL);" -psql:include/cagg_migrate_common.sql:274: NOTICE: drop cascades to 6 other objects -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1026 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1025 not found, skipping -psql:include/cagg_migrate_common.sql:274: NOTICE: job 1024 not found, skipping --- cagg with the new format because it was overriden -\d+ conditions_summary_daily - View "public.conditions_summary_daily" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | - min | numeric | | | | main | - max | numeric | | | | main | - avg | numeric | | | | main | - sum | numeric | | | | main | -View definition: - SELECT _materialized_hypertable_37.bucket, - _materialized_hypertable_37.min, - _materialized_hypertable_37.max, - _materialized_hypertable_37.avg, - _materialized_hypertable_37.sum - 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 day'::interval, conditions."time") AS bucket, - min(conditions.temperature) AS min, - max(conditions.temperature) AS max, - avg(conditions.temperature) AS avg, - sum(conditions.temperature) AS sum - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(37)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::interval, conditions."time")); - -\set ON_ERROR_STOP 0 --- should fail because the cagg was overriden -SELECT * FROM conditions_summary_daily_new; -psql:include/cagg_migrate_common.sql:279: ERROR: relation "conditions_summary_daily_new" does not exist at character 15 --- should fail because the old cagg was removed -SELECT * FROM conditions_summary_daily_old; -psql:include/cagg_migrate_common.sql:281: ERROR: relation "conditions_summary_daily_old" does not exist at character 15 -\set ON_ERROR_STOP 1 --- check policies after the migration -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+--------------------------+------+--------------------------------------------+-------------------+-------------+-------------+--------------+------------------------+-------------------------------------+--------------------+-----------+----------------+---------------+---------------+---------------------------------------------------------------------------------+------------------------+-------------------------------------------+---------- - public | conditions_summary_daily | 1033 | Retention Policy [1033] | @ 1 day | @ 5 mins | -1 | @ 5 mins | _timescaledb_functions | policy_retention | cluster_super_user | t | f | | 37 | {"drop_after": "@ 30 days", "hypertable_id": 37} | _timescaledb_functions | policy_retention_check | - public | conditions_summary_daily | 1034 | Refresh Continuous Aggregate Policy [1034] | @ 1 hour | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_refresh_continuous_aggregate | cluster_super_user | t | f | | 37 | {"end_offset": "@ 1 day", "start_offset": "@ 30 days", "mat_hypertable_id": 37} | _timescaledb_functions | policy_refresh_continuous_aggregate_check | - public | conditions_summary_daily | 1035 | Compression Policy [1035] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | cluster_super_user | t | f | | 37 | {"hypertable_id": 37, "compress_after": "@ 45 days"} | _timescaledb_functions | policy_compression_check | -(3 rows) - --- should return no rows because the old cagg was removed -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_old'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- should return no rows because the cagg was overwritten -SELECT * FROM cagg_jobs WHERE schema = 'public' AND name = 'conditions_summary_daily_new'; - schema | name | id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone ---------+------+----+------------------+-------------------+-------------+-------------+--------------+-------------+-----------+-------+-----------+----------------+---------------+---------------+--------+--------------+------------+---------- -(0 rows) - --- permission tests -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:291: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -GRANT ALL ON TABLE conditions TO :ROLE_DEFAULT_PERM_USER; -ALTER MATERIALIZED VIEW conditions_summary_weekly OWNER TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:298: ERROR: permission denied for table continuous_agg_migrate_plan -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step' catalog table -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:308: ERROR: permission denied for sequence continuous_agg_migrate_plan_step_step_id_seq -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan_step TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 --- should fail because the lack of permissions on 'continuous_agg_migrate_plan_step_step_id_seq' catalog sequence -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:318: ERROR: permission denied for sequence continuous_agg_migrate_plan_step_step_id_seq -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq TO :ROLE_DEFAULT_PERM_USER; -SET ROLE :ROLE_DEFAULT_PERM_USER; --- all necessary permissions granted -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:327: WARNING: refresh the continuous aggregate after the migration executing this statement: "CALL public.refresh_continuous_aggregate('public.conditions_summary_weekly_new', CAST('Mon Jan 02 00:00:00 2023' AS timestamp with time zone), NULL);" --- check migrated data. should return 0 (zero) rows -SELECT * FROM conditions_summary_weekly -EXCEPT -SELECT * FROM conditions_summary_weekly_new; - bucket | min | max | avg | sum ---------+-----+-----+-----+----- -(0 rows) - -SELECT mat_hypertable_id, step_id, status, type, config FROM _timescaledb_catalog.continuous_agg_migrate_plan_step ORDER BY step_id; - mat_hypertable_id | step_id | status | type | config --------------------+---------+----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 30 | 1 | FINISHED | SAVE WATERMARK | {"watermark": "Mon Jan 02 00:00:00 2023"} - 30 | 2 | FINISHED | CREATE NEW CAGG | {"cagg_name_new": "conditions_summary_weekly_new"} - 30 | 3 | FINISHED | DISABLE POLICIES | {"policies": null} - 30 | 4 | FINISHED | REFRESH NEW CAGG | {"window_start": "Mon Jan 02 00:00:00 2023", "cagg_name_new": "conditions_summary_weekly_new", "window_start_type": "timestamp with time zone"} - 30 | 5 | FINISHED | COPY DATA | {"end_ts": "Sun Mar 06 16:00:00 2022 PST", "start_ts": "Sun Dec 26 16:00:00 2021 PST", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 6 | FINISHED | COPY DATA | {"end_ts": "Sun May 15 16:00:00 2022 PDT", "start_ts": "Sun Mar 06 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 7 | FINISHED | COPY DATA | {"end_ts": "Sun Jul 24 16:00:00 2022 PDT", "start_ts": "Sun May 15 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 8 | FINISHED | COPY DATA | {"end_ts": "Sun Oct 02 16:00:00 2022 PDT", "start_ts": "Sun Jul 24 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 9 | FINISHED | COPY DATA | {"end_ts": "Sun Dec 11 16:00:00 2022 PST", "start_ts": "Sun Oct 02 16:00:00 2022 PDT", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 10 | FINISHED | COPY DATA | {"end_ts": "Sun Feb 19 16:00:00 2023 PST", "start_ts": "Sun Dec 11 16:00:00 2022 PST", "cagg_name_new": "conditions_summary_weekly_new", "bucket_column_name": "bucket", "bucket_column_type": "timestamp with time zone"} - 30 | 11 | FINISHED | COPY POLICIES | {"policies": null, "cagg_name_new": "conditions_summary_weekly_new"} - 30 | 12 | FINISHED | OVERRIDE CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 30 | 13 | FINISHED | DROP OLD CAGG | {"drop_old": false, "override": false, "cagg_name_new": "conditions_summary_weekly_new"} - 30 | 14 | FINISHED | ENABLE POLICIES | -(14 rows) - -RESET ROLE; --- according to the official documentation trying to execute a procedure with --- transaction control statements inside an explicit transaction should fail: --- https://www.postgresql.org/docs/current/sql-call.html --- `If CALL is executed in a transaction block, then the called procedure cannot --- execute transaction control statements. Transaction control statements are only --- allowed if CALL is executed in its own transaction.` -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:344: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_weekly_new; -psql:include/cagg_migrate_common.sql:345: NOTICE: drop cascades to 6 other objects -\set ON_ERROR_STOP 0 -BEGIN; --- should fail with `invalid transaction termination` -CALL cagg_migrate('conditions_summary_weekly'); -psql:include/cagg_migrate_common.sql:350: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 -CREATE FUNCTION execute_migration() RETURNS void AS -$$ -BEGIN - CALL cagg_migrate('conditions_summary_weekly'); - RETURN; -END; -$$ -LANGUAGE plpgsql; -\set ON_ERROR_STOP 0 --- execute migration inside a plpgsql function -BEGIN; --- should fail with `invalid transaction termination` -SELECT execute_migration(); -psql:include/cagg_migrate_common.sql:367: ERROR: invalid transaction termination -ROLLBACK; -\set ON_ERROR_STOP 1 --- cleanup -DROP FUNCTION execute_migration(); -REVOKE SELECT, INSERT, UPDATE ON TABLE _timescaledb_catalog.continuous_agg_migrate_plan FROM :ROLE_DEFAULT_PERM_USER; -REVOKE USAGE ON SEQUENCE _timescaledb_catalog.continuous_agg_migrate_plan_step_step_id_seq FROM :ROLE_DEFAULT_PERM_USER; -TRUNCATE _timescaledb_catalog.continuous_agg_migrate_plan RESTART IDENTITY CASCADE; -psql:include/cagg_migrate_common.sql:375: NOTICE: truncate cascades to table "continuous_agg_migrate_plan_step" -DROP MATERIALIZED VIEW conditions_summary_daily; -psql:include/cagg_migrate_common.sql:376: NOTICE: drop cascades to 6 other objects -DROP MATERIALIZED VIEW conditions_summary_weekly; -psql:include/cagg_migrate_common.sql:377: NOTICE: drop cascades to 6 other objects -DROP TABLE conditions; --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_on_cagg_dist_ht.out b/tsl/test/expected/cagg_on_cagg_dist_ht.out deleted file mode 100644 index 5b595dcebb5..00000000000 --- a/tsl/test/expected/cagg_on_cagg_dist_ht.out +++ /dev/null @@ -1,5898 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set INTERVAL_TEST FALSE -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT (add_data_node (name, host => 'localhost', DATABASE => name)).* -FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v (name); -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | host | port | database | node_created | database_created | extension_created ----------------------------+-----------+-------+---------------------------+--------------+------------------+------------------- - db_cagg_on_cagg_dist_ht_1 | localhost | 55432 | db_cagg_on_cagg_dist_ht_1 | t | t | t - db_cagg_on_cagg_dist_ht_2 | localhost | 55432 | db_cagg_on_cagg_dist_ht_2 | t | t | t - db_cagg_on_cagg_dist_ht_3 | localhost | 55432 | db_cagg_on_cagg_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- PG15 requires this explicit GRANT on schema public -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; --- Global test variables -\set IS_DISTRIBUTED TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE -\set IS_JOIN FALSE --- ######################################################## --- ## INTEGER data type tests --- ######################################################## --- Current test variables -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\set INTERVAL_TEST FALSE -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 --- --- Run common tests for INTEGER --- -\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:39: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - set_integer_now_func ----------------------- - -(1 row) - - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 - 10 | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 17 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 37 - 10 | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 17 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 37 - 10 | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_4_4_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_3_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_2_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:39: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - set_integer_now_func ----------------------- - -(1 row) - - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 15 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 35 - 10 | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 17 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 37 - 10 | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- - 0 | 17 - 5 | 20 - 10 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- - 0 | 37 - 10 | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_8_9_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_8_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_6_7_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for non-multiple bucket sizes --- -\set 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 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 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; --- cleanup -DROP TABLE conditions; --- ######################################################## --- ## 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 timezone TO 'UTC'; --- --- Run common tests for TIMESTAMP --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated -psql:include/cagg_on_cagg_setup.sql:37: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 17 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 37 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 17 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 37 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_16_14_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_15_13_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_12_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated -psql:include/cagg_on_cagg_setup.sql:37: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 15 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 35 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 17 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 37 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------------------------+------------- - Sat Jan 01 00:00:00 2022 | 17 - Sun Jan 02 00:00:00 2022 | 20 - Mon Jan 03 00:00:00 2022 | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------------------------+------------- - Mon Dec 27 00:00:00 2021 | 37 - Mon Jan 03 00:00:00 2022 | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_20_18_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_19_17_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_18_16_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for variable bucket on top of fixed bucket --- -\set 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 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 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 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 IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 17 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 37 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 17 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 37 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_29_22_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_21_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_20_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature ---------+------------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 -(2 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 -(1 row) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 15 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 35 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 17 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 37 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature -------------------------------+------------- - Sat Jan 01 00:00:00 2022 UTC | 17 - Sun Jan 02 00:00:00 2022 UTC | 20 - Mon Jan 03 00:00:00 2022 UTC | 2 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature -------------------------------+------------- - Mon Dec 27 00:00:00 2021 UTC | 37 - Mon Jan 03 00:00:00 2022 UTC | 2 -(2 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_33_26_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature ---------+------------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_32_25_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_31_24_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for variable bucket on top of fixed bucket --- -\set 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 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 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 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 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; ---#Bugfix 5734 #1 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH '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_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 hour'::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(44)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 hour'::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_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 day'::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 day'::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; -psql:include/cagg_on_cagg_validations.sql:71: NOTICE: refreshing continuous aggregate "conditions_summary_3" - \d+ :CAGG_NAME_3TH_LEVEL - View "public.conditions_summary_3" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | -View definition: - SELECT _materialized_hypertable_46.bucket - 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 mon'::interval, conditions_summary_2.bucket, 'UTC'::text) AS bucket - FROM conditions_summary_2 - WHERE conditions_summary_2.bucket >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(46)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_2.bucket, 'UTC'::text)); - - --There should never be dulpicates in the output of the following query - SELECT * from :CAGG_NAME_3TH_LEVEL; - bucket ------------------------------- - Sat Jan 01 00:00:00 2022 UTC -(1 row) - - DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_validations.sql:79: NOTICE: drop cascades to table _timescaledb_internal._hyper_46_31_chunk - 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: drop cascades to table _timescaledb_internal._hyper_45_30_chunk -DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_validations.sql:87: NOTICE: drop cascades to table _timescaledb_internal._hyper_44_29_chunk -\set INTERVAL_TEST FALSE --- --- 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_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 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(47)), '-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_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 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(48)), '-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; ---#Bugfix 5734 #2 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH '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_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 hour'::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(49)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 hour'::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_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_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(50)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::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; -psql:include/cagg_on_cagg_validations.sql:71: NOTICE: refreshing continuous aggregate "conditions_summary_3" - \d+ :CAGG_NAME_3TH_LEVEL - View "public.conditions_summary_3" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | -View definition: - SELECT _materialized_hypertable_51.bucket - 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 mon'::interval, conditions_summary_2.bucket, 'UTC'::text) AS bucket - FROM conditions_summary_2 - WHERE conditions_summary_2.bucket >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(51)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_2.bucket, 'UTC'::text)); - - --There should never be dulpicates in the output of the following query - SELECT * from :CAGG_NAME_3TH_LEVEL; - bucket ------------------------------- - Sat Jan 01 00:00:00 2022 UTC -(1 row) - - DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_validations.sql:79: NOTICE: drop cascades to table _timescaledb_internal._hyper_51_34_chunk - 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: drop cascades to table _timescaledb_internal._hyper_50_33_chunk -DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_validations.sql:87: NOTICE: drop cascades to table _timescaledb_internal._hyper_49_32_chunk -\set INTERVAL_TEST FALSE --- --- 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_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") 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")); - --- --- 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('@ 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(53)), '-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; ---#Bugfix 5734 #3 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH '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_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 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(54)), '-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 -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 day'::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(55)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 day'::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; -psql:include/cagg_on_cagg_validations.sql:71: NOTICE: refreshing continuous aggregate "conditions_summary_3" - \d+ :CAGG_NAME_3TH_LEVEL - View "public.conditions_summary_3" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+--------------------------+-----------+----------+---------+---------+------------- - bucket | timestamp with time zone | | | | plain | -View definition: - SELECT _materialized_hypertable_56.bucket - 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('@ 1 mon'::interval, conditions_summary_2.bucket, 'UTC'::text) AS bucket - FROM conditions_summary_2 - WHERE conditions_summary_2.bucket >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(56)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 mon'::interval, conditions_summary_2.bucket, 'UTC'::text)); - - --There should never be dulpicates in the output of the following query - SELECT * from :CAGG_NAME_3TH_LEVEL; - bucket ------------------------------- - Sat Jan 01 00:00:00 2022 UTC -(1 row) - - DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_validations.sql:79: NOTICE: drop cascades to table _timescaledb_internal._hyper_56_37_chunk - 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: drop cascades to table _timescaledb_internal._hyper_55_36_chunk -DROP MATERIALIZED VIEW IF EXISTS :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_validations.sql:87: NOTICE: drop cascades to table _timescaledb_internal._hyper_54_35_chunk -\set INTERVAL_TEST FALSE --- --- 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_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('@ 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(57)), '-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_58.bucket, - _materialized_hypertable_58.temperature - FROM _timescaledb_internal._materialized_hypertable_58 - WHERE _materialized_hypertable_58.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(58)), '-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(58)), '-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; -\set INTERVAL_TEST FALSE --- 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_59.bucket, - _materialized_hypertable_59.temperature - FROM _timescaledb_internal._materialized_hypertable_59 - WHERE _materialized_hypertable_59.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(59)), '-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(59)), '-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_60.bucket, - _materialized_hypertable_60.temperature - FROM _timescaledb_internal._materialized_hypertable_60 - WHERE _materialized_hypertable_60.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(60)), '-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(60)), '-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_61.bucket, - _materialized_hypertable_61.temperature - FROM _timescaledb_internal._materialized_hypertable_61 - WHERE _materialized_hypertable_61.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(61)), '-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(61)), '-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_62.bucket, - _materialized_hypertable_62.temperature - FROM _timescaledb_internal._materialized_hypertable_62 - WHERE _materialized_hypertable_62.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(62)), '-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(62)), '-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_63.bucket, - _materialized_hypertable_63.temperature - FROM _timescaledb_internal._materialized_hypertable_63 - WHERE _materialized_hypertable_63.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(63)), '-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(63)), '-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_64.bucket, - _materialized_hypertable_64.temperature - FROM _timescaledb_internal._materialized_hypertable_64 - WHERE _materialized_hypertable_64.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(64)), '-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(64)), '-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_65.bucket, - _materialized_hypertable_65.temperature - FROM _timescaledb_internal._materialized_hypertable_65 - WHERE _materialized_hypertable_65.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(65)), '-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(65)), '-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_66.bucket, - _materialized_hypertable_66.temperature - FROM _timescaledb_internal._materialized_hypertable_66 - WHERE _materialized_hypertable_66.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(66)), '-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(66)), '-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; --- bug report 5277 -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE --- epoch plus cast to int would compute a bucket width of 0 for parent -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 ms\'' -\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_67.bucket, - _materialized_hypertable_67.temperature - FROM _timescaledb_internal._materialized_hypertable_67 - WHERE _materialized_hypertable_67.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(67)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(67)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.146 secs'::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_68.bucket, - _materialized_hypertable_68.temperature - FROM _timescaledb_internal._materialized_hypertable_68 - WHERE _materialized_hypertable_68.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(68)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1.168 secs'::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(68)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1.168 secs'::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 \'9344 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'74752 ms\'' -\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_69.bucket, - _materialized_hypertable_69.temperature - FROM _timescaledb_internal._materialized_hypertable_69 - WHERE _materialized_hypertable_69.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(69)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 9.344 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(69)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 9.344 secs'::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_70.bucket, - _materialized_hypertable_70.temperature - FROM _timescaledb_internal._materialized_hypertable_70 - WHERE _materialized_hypertable_70.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(70)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1 min 14.752 secs'::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(70)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 min 14.752 secs'::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 \'74752 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'598016 ms\'' -\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_71.bucket, - _materialized_hypertable_71.temperature - FROM _timescaledb_internal._materialized_hypertable_71 - WHERE _materialized_hypertable_71.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(71)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1 min 14.752 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(71)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 min 14.752 secs'::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_72.bucket, - _materialized_hypertable_72.temperature - FROM _timescaledb_internal._materialized_hypertable_72 - WHERE _materialized_hypertable_72.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(72)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 9 mins 58.016 secs'::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(72)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 9 mins 58.016 secs'::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 microseconds - should pass -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 usec\'' -\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_73.bucket, - _materialized_hypertable_73.temperature - FROM _timescaledb_internal._materialized_hypertable_73 - WHERE _materialized_hypertable_73.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(73)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.000146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(73)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.000146 secs'::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_74.bucket, - _materialized_hypertable_74.temperature - FROM _timescaledb_internal._materialized_hypertable_74 - WHERE _materialized_hypertable_74.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(74)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.001168 secs'::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(74)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.001168 secs'::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 microseconds - SHOULD FAIL -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1160 usec\'' -\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_75.bucket, - _materialized_hypertable_75.temperature - FROM _timescaledb_internal._materialized_hypertable_75 - WHERE _materialized_hypertable_75.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(75)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.000146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(75)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.000146 secs'::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; -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" [@ 0.00116 secs] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 0.000146 secs]. -\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; --- Cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/cagg_on_cagg_joins_dist_ht.out b/tsl/test/expected/cagg_on_cagg_joins_dist_ht.out deleted file mode 100644 index 55678a675cb..00000000000 --- a/tsl/test/expected/cagg_on_cagg_joins_dist_ht.out +++ /dev/null @@ -1,5546 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set INTERVAL_TEST FALSE -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SELECT (add_data_node (name, host => 'localhost', DATABASE => name)).* -FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v (name); -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | host | port | database | node_created | database_created | extension_created ----------------------------------+-----------+-------+---------------------------------+--------------+------------------+------------------- - db_cagg_on_cagg_joins_dist_ht_1 | localhost | 55432 | db_cagg_on_cagg_joins_dist_ht_1 | t | t | t - db_cagg_on_cagg_joins_dist_ht_2 | localhost | 55432 | db_cagg_on_cagg_joins_dist_ht_2 | t | t | t - db_cagg_on_cagg_joins_dist_ht_3 | localhost | 55432 | db_cagg_on_cagg_joins_dist_ht_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- PG15 requires this explicit GRANT on schema public -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; --- Global test variables -\set IS_DISTRIBUTED TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE -\set IS_JOIN TRUE --- ######################################################## --- ## INTEGER data type tests --- ######################################################## --- Current test variables -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 --- --- Run common tests for INTEGER --- -\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; -psql:include/cagg_on_cagg_setup.sql:30: NOTICE: table "devices" does not exist, skipping - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:39: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - set_integer_now_func ----------------------- - -(1 row) - - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 10 | 1 - 0 | 5 | 2 - 0 | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_4_4_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_3_3_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_2_2_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:39: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - set_integer_now_func ----------------------- - -(1 row) - - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 10 | 1 - 0 | 5 | 2 - 0 | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 5 | 2 - 0 | 10 | 1 - 5 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 0 | 20 | 3 - 0 | 5 | 2 - 0 | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_1 because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_5 because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_1" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_5" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_8_9_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_10" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_7_8_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_5" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- - 1 | 10 | 1 - 2 | 2 | - 2 | 5 | 2 - 5 | 20 | 3 - 10 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_6_7_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_1" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for non-multiple bucket sizes --- -\set 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 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 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; --- cleanup -DROP TABLE conditions; --- ######################################################## --- ## 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 timezone TO 'UTC'; --- --- Run common tests for TIMESTAMP --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -psql:include/cagg_on_cagg_setup.sql:14: NOTICE: table "conditions" does not exist, skipping -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated -psql:include/cagg_on_cagg_setup.sql:37: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 10 | 1 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_16_14_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_15_13_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_14_12_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated -psql:include/cagg_on_cagg_setup.sql:37: WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 10 | 1 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 5 | 2 - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sun Jan 02 00:00:00 2022 | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 | 20 | 3 - Mon Dec 27 00:00:00 2021 | 5 | 2 - Mon Dec 27 00:00:00 2021 | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_20_18_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_19_17_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 | 10 | 1 - Sat Jan 01 01:00:00 2022 | 2 | - Sat Jan 01 01:00:00 2022 | 5 | 2 - Sun Jan 02 01:00:00 2022 | 20 | 3 - Mon Jan 03 01:00:00 2022 | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_18_16_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for variable bucket on top of fixed bucket --- -\set 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 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 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 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 IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_29_22_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_28_21_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_27_20_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGGs on CAGGs tests -\if :IS_DISTRIBUTED -\echo 'Running distributed hypertable tests' -Running distributed hypertable tests -\else -\echo 'Running local hypertable tests' -\endif -SET ROLE :ROLE_DEFAULT_PERM_USER; -DROP TABLE IF EXISTS conditions CASCADE; -\if :IS_DEFAULT_COLUMN_ORDER - CREATE TABLE conditions ( - time :TIME_DIMENSION_DATATYPE NOT NULL, - temperature NUMERIC, - device_id INT - ); -\else - CREATE TABLE conditions ( - temperature NUMERIC, - time :TIME_DIMENSION_DATATYPE NOT NULL, - device_id INT - ); -\endif -\if :IS_JOIN - DROP TABLE IF EXISTS devices CASCADE; - CREATE TABLE devices ( device_id int not null, name text, location text); - INSERT INTO devices values (1, 'thermo_1', 'Moscow'), (2, 'thermo_2', 'Berlin'),(3, 'thermo_3', 'London'),(4, 'thermo_4', 'Stockholm'); -\endif -\if :IS_DISTRIBUTED - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', replication_factor => 2); -psql:include/cagg_on_cagg_setup.sql:37: WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - - \else - SELECT table_name FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => 10, replication_factor => 2); - \endif -\else - \if :IS_TIME_DIMENSION - SELECT table_name FROM create_hypertable('conditions', 'time'); - \else - SELECT table_name FROM create_hypertable('conditions', 'time', chunk_time_interval => 10); - \endif -\endif -\if :IS_TIME_DIMENSION - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 00:00:00-00', 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-01 01:00:00-00', 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES ('2022-01-02 01:00:00-00', 20, 3); -\else - CREATE OR REPLACE FUNCTION integer_now() - RETURNS :TIME_DIMENSION_DATATYPE LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - \if :IS_DISTRIBUTED - SELECT - 'CREATE OR REPLACE FUNCTION integer_now() RETURNS '||:'TIME_DIMENSION_DATATYPE'||' LANGUAGE SQL STABLE AS $$ SELECT coalesce(max(time), 0) FROM conditions $$;' AS "STMT" - \gset - CALL distributed_exec (:'STMT'); - \endif - SELECT set_integer_now_func('conditions', 'integer_now'); - INSERT INTO conditions ("time", temperature, device_id) VALUES (1, 10, 1); - INSERT INTO conditions ("time", temperature, device_id) VALUES (2, 5, 2); - INSERT INTO conditions ("time", temperature, device_id) VALUES (5, 20, 3); -\endif -\ir include/cagg_on_cagg_common.sql --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. --- CAGG on hypertable (1st level) -CREATE MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_1ST, "time") AS bucket, - SUM(temperature) AS temperature, - device_id -FROM conditions -GROUP BY 1,3 -WITH NO DATA; --- CAGG on CAGG (2th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL -WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS -SELECT - time_bucket(:BUCKET_WIDTH_2TH, "bucket") AS bucket, - SUM(temperature) AS temperature -\if :IS_JOIN - , :CAGG_NAME_1ST_LEVEL.device_id - FROM :CAGG_NAME_1ST_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_1ST_LEVEL.device_id - GROUP BY 1,3 -\else - FROM :CAGG_NAME_1ST_LEVEL - GROUP BY 1 -\endif -WITH NO DATA; --- CAGG on CAGG (3th level) -CREATE MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL - WITH (timescaledb.continuous, timescaledb.materialized_only=true) AS - SELECT - time_bucket(:BUCKET_WIDTH_3TH, "bucket") AS bucket, - SUM(temperature) AS temperature - \if :IS_JOIN - , :CAGG_NAME_2TH_LEVEL.device_id - FROM :CAGG_NAME_2TH_LEVEL, devices - WHERE devices.device_id = :CAGG_NAME_2TH_LEVEL.device_id - GROUP BY 1,3 - \else - FROM :CAGG_NAME_2TH_LEVEL - GROUP BY 1 - \endif - WITH NO DATA; --- Check chunk_interval -\if :IS_TIME_DIMENSION - SELECT h.table_name AS name, _timescaledb_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 -(4 rows) - -\else - SELECT h.table_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.hypertable h - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = h.id - WHERE h.table_name = 'conditions' - UNION ALL - SELECT c.user_view_name AS name, d.interval_length AS chunk_interval - FROM _timescaledb_catalog.continuous_agg c - LEFT JOIN _timescaledb_catalog.dimension d on d.hypertable_id = c.mat_hypertable_id - WHERE c.user_view_name IN (:'CAGG_NAME_1ST_LEVEL', :'CAGG_NAME_2TH_LEVEL', :'CAGG_NAME_3TH_LEVEL') - ORDER BY 1, 2; -\endif --- No data because the CAGGs are just for materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); ---ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - ---SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Materialized data -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - -\if :IS_TIME_DIMENSION --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-01 01:00:00-00'::timestamptz, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES ('2022-01-03 01:00:00-00'::timestamptz, 2); -\else --- Invalidate an old region -INSERT INTO conditions ("time", temperature) VALUES (2, 2); --- New region -INSERT INTO conditions ("time", temperature) VALUES (10, 2); -\endif --- No changes -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- Turn CAGGs into Realtime -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=false); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=false); --- Realtime changes, just new region -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(4 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 -(3 rows) - --- Turn CAGGs into materialized only again -ALTER MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL SET (timescaledb.materialized_only=true); -ALTER MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL SET (timescaledb.materialized_only=true); --- Refresh all data -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- All changes are materialized -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- TRUNCATE tests -TRUNCATE :CAGG_NAME_2TH_LEVEL; --- This full refresh will remove all the data from the 3TH level cagg -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Should return no rows -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- If we have all the data in the bottom levels caggs we can rebuild -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_3TH_LEVEL', NULL, NULL); --- Now we have all the data -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket, temperature; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 5 | 2 - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sun Jan 02 00:00:00 2022 UTC | 20 | 3 -(3 rows) - -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Mon Dec 27 00:00:00 2021 UTC | 20 | 3 - Mon Dec 27 00:00:00 2021 UTC | 5 | 2 - Mon Dec 27 00:00:00 2021 UTC | 10 | 1 -(3 rows) - --- DROP tests -\set ON_ERROR_STOP 0 --- should error because it depends of other CAGGs -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:166: ERROR: cannot drop view conditions_summary_1_hourly because other objects depend on it -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:167: ERROR: cannot drop view conditions_summary_2_daily because other objects depend on it -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:168: NOTICE: continuous aggregate "conditions_summary_1_hourly" is already up-to-date -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -psql:include/cagg_on_cagg_common.sql:169: NOTICE: continuous aggregate "conditions_summary_2_daily" is already up-to-date -\set ON_ERROR_STOP 1 --- DROP the 3TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_3TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:173: NOTICE: drop cascades to table _timescaledb_internal._hyper_33_26_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_3TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:176: ERROR: relation "conditions_summary_3_weekly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -TRUNCATE :CAGG_NAME_2TH_LEVEL,:CAGG_NAME_1ST_LEVEL; -CALL refresh_continuous_aggregate(:'CAGG_NAME_2TH_LEVEL', NULL, NULL); -CALL refresh_continuous_aggregate(:'CAGG_NAME_1ST_LEVEL', NULL, NULL); -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; - bucket | temperature | device_id ---------+-------------+----------- -(0 rows) - --- DROP the 2TH level CAGG don't affect others -DROP MATERIALIZED VIEW :CAGG_NAME_2TH_LEVEL; -psql:include/cagg_on_cagg_common.sql:187: NOTICE: drop cascades to table _timescaledb_internal._hyper_32_25_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_2TH_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:190: ERROR: relation "conditions_summary_2_daily" does not exist at character 15 -\set ON_ERROR_STOP 1 --- should work because dropping the top level CAGG --- don't affect the down level CAGGs -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; - bucket | temperature | device_id -------------------------------+-------------+----------- - Sat Jan 01 00:00:00 2022 UTC | 10 | 1 - Sat Jan 01 01:00:00 2022 UTC | 2 | - Sat Jan 01 01:00:00 2022 UTC | 5 | 2 - Sun Jan 02 01:00:00 2022 UTC | 20 | 3 - Mon Jan 03 01:00:00 2022 UTC | 2 | -(5 rows) - --- DROP the first CAGG should work -DROP MATERIALIZED VIEW :CAGG_NAME_1ST_LEVEL; -psql:include/cagg_on_cagg_common.sql:197: NOTICE: drop cascades to table _timescaledb_internal._hyper_31_24_chunk -\set ON_ERROR_STOP 0 --- should error because it was dropped -SELECT * FROM :CAGG_NAME_1ST_LEVEL ORDER BY bucket; -psql:include/cagg_on_cagg_common.sql:200: ERROR: relation "conditions_summary_1_hourly" does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Validation test for variable bucket on top of fixed bucket --- -\set 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 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 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 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 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; --- 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; --- bug report 5277 -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE --- epoch plus cast to int would compute a bucket width of 0 for parent -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 ms\'' -\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_58.bucket, - _materialized_hypertable_58.temperature - FROM _timescaledb_internal._materialized_hypertable_58 - WHERE _materialized_hypertable_58.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(58)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(58)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.146 secs'::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_59.bucket, - _materialized_hypertable_59.temperature - FROM _timescaledb_internal._materialized_hypertable_59 - WHERE _materialized_hypertable_59.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(59)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1.168 secs'::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(59)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1.168 secs'::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 \'9344 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'74752 ms\'' -\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_60.bucket, - _materialized_hypertable_60.temperature - FROM _timescaledb_internal._materialized_hypertable_60 - WHERE _materialized_hypertable_60.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(60)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 9.344 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(60)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 9.344 secs'::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_61.bucket, - _materialized_hypertable_61.temperature - FROM _timescaledb_internal._materialized_hypertable_61 - WHERE _materialized_hypertable_61.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(61)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1 min 14.752 secs'::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(61)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 min 14.752 secs'::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 \'74752 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'598016 ms\'' -\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_62.bucket, - _materialized_hypertable_62.temperature - FROM _timescaledb_internal._materialized_hypertable_62 - WHERE _materialized_hypertable_62.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(62)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 1 min 14.752 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(62)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 1 min 14.752 secs'::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_63.bucket, - _materialized_hypertable_63.temperature - FROM _timescaledb_internal._materialized_hypertable_63 - WHERE _materialized_hypertable_63.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(63)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 9 mins 58.016 secs'::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(63)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 9 mins 58.016 secs'::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 microseconds - should pass -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 usec\'' -\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_64.bucket, - _materialized_hypertable_64.temperature - FROM _timescaledb_internal._materialized_hypertable_64 - WHERE _materialized_hypertable_64.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(64)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.000146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(64)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.000146 secs'::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_65.bucket, - _materialized_hypertable_65.temperature - FROM _timescaledb_internal._materialized_hypertable_65 - WHERE _materialized_hypertable_65.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(65)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.001168 secs'::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(65)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.001168 secs'::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 microseconds - SHOULD FAIL -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1160 usec\'' -\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_66.bucket, - _materialized_hypertable_66.temperature - FROM _timescaledb_internal._materialized_hypertable_66 - WHERE _materialized_hypertable_66.bucket < COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(66)), '-infinity'::timestamp with time zone) -UNION ALL - SELECT time_bucket('@ 0.000146 secs'::interval, conditions."time") AS bucket, - sum(conditions.temperature) AS temperature - FROM conditions - WHERE conditions."time" >= COALESCE(_timescaledb_functions.to_timestamp(_timescaledb_functions.cagg_watermark(66)), '-infinity'::timestamp with time zone) - GROUP BY (time_bucket('@ 0.000146 secs'::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; -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" [@ 0.00116 secs] should be multiple of the time bucket width of "public.conditions_summary_1" [@ 0.000146 secs]. -\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; --- Cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/data_fetcher.out b/tsl/test/expected/data_fetcher.out deleted file mode 100644 index 2c66d7b8b33..00000000000 --- a/tsl/test/expected/data_fetcher.out +++ /dev/null @@ -1,198 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set TEST_BASE_NAME data_fetcher -SELECT format('include/%s_run.sql', :'TEST_BASE_NAME') as "TEST_QUERY_NAME", - format('%s/results/%s_results_cursor.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_CURSOR", - format('%s/results/%s_results_copy.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_COPY", - format('%s/results/%s_results_prepared.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_PREPARED" -\gset -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------------+-------------------+--------------+------------------+------------------- - db_data_fetcher_1 | db_data_fetcher_1 | t | t | t - db_data_fetcher_2 | db_data_fetcher_2 | t | t | t - db_data_fetcher_3 | db_data_fetcher_3 | t | t | t -(3 rows) - -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - -SELECT setseed(1); - setseed ---------- - -(1 row) - -INSERT INTO disttable -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random() * 10 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-02'::timestamptz, '1 second') as t; --- This table contains the content for precisely one batch of the copy fetcher. The fetch_size --- will be set to 100 below and this table contains 99 tuples and the last element on the first --- copy batch is the file trailer (#5323). -CREATE table one_batch(ts timestamptz NOT NULL, sensor_id int NOT NULL, value float NOT NULL); -SELECT create_distributed_hypertable('one_batch', 'ts'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,one_batch,t) -(1 row) - -INSERT INTO one_batch SELECT '2023-01-01'::timestamptz AS time, sensor_id, random() AS value FROM generate_series(1, 99, 1) AS g1(sensor_id) ORDER BY time; --- Same but for the DEFAULT_FDW_FETCH_SIZE (10000) -CREATE table one_batch_default(ts timestamptz NOT NULL, sensor_id int NOT NULL, value float NOT NULL); -SELECT create_distributed_hypertable('one_batch_default', 'ts'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (3,public,one_batch_default,t) -(1 row) - -INSERT INTO one_batch_default SELECT '2023-01-01'::timestamptz AS time, sensor_id, random() AS value FROM generate_series(1, 9999, 1) AS g1(sensor_id) ORDER BY time; -SET client_min_messages TO error; --- Set a smaller fetch size to ensure that the result is split into --- mutliple batches. -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '100'); --- run the queries using COPY fetcher -SET timescaledb.remote_data_fetcher = 'copy'; -\set ON_ERROR_STOP 0 -\o :TEST_RESULTS_COPY -\ir :TEST_QUERY_NAME --- 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. -ANALYZE disttable; -SELECT count(*) FROM disttable; -SELECT time_bucket('1 hour', time) AS time, device, avg(temp) -FROM disttable -GROUP BY 1,2 -ORDER BY 1,2; --- Test for #5323 - ensure that no NULL tuples are generated --- if the last element of the batch is the file trailer. -SELECT count(*), count(value) FROM one_batch; -SELECT count(*), count(value) FROM one_batch_default; -\o -\set ON_ERROR_STOP 1 --- run queries using cursor fetcher -SET timescaledb.remote_data_fetcher = 'cursor'; -\o :TEST_RESULTS_CURSOR -\ir :TEST_QUERY_NAME --- 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. -ANALYZE disttable; -SELECT count(*) FROM disttable; -SELECT time_bucket('1 hour', time) AS time, device, avg(temp) -FROM disttable -GROUP BY 1,2 -ORDER BY 1,2; --- Test for #5323 - ensure that no NULL tuples are generated --- if the last element of the batch is the file trailer. -SELECT count(*), count(value) FROM one_batch; -SELECT count(*), count(value) FROM one_batch_default; -\o --- compare results -SELECT format('\! diff %s %s', :'TEST_RESULTS_CURSOR', :'TEST_RESULTS_COPY') as "DIFF_CMD" -\gset -:DIFF_CMD --- run queries using prepares statement fetcher -SET timescaledb.remote_data_fetcher = 'prepared'; -\o :TEST_RESULTS_PREPARED -\ir :TEST_QUERY_NAME --- 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. -ANALYZE disttable; -SELECT count(*) FROM disttable; -SELECT time_bucket('1 hour', time) AS time, device, avg(temp) -FROM disttable -GROUP BY 1,2 -ORDER BY 1,2; --- Test for #5323 - ensure that no NULL tuples are generated --- if the last element of the batch is the file trailer. -SELECT count(*), count(value) FROM one_batch; -SELECT count(*), count(value) FROM one_batch_default; -\o --- compare results -SELECT format('\! diff %s %s', :'TEST_RESULTS_CURSOR', :'TEST_RESULTS_PREPARED') as "DIFF_CMD" -\gset -:DIFF_CMD --- Test custom FDW settings. Instead of the tests above, we are not interersted --- in comparing the results of the fetchers. In the following tests we are --- interested in the actual outputs (e.g., costs). It's enough to only test them --- with one type of fetcher, because it doesn't influence the costs. -ANALYZE one_batch; -SET timescaledb.remote_data_fetcher = 'copy'; -\ir include/data_fetcher_fdw_settings.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. --- Default settings -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN -------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=10000.00..10101.98 rows=99 width=20) -(1 row) - --- Set custom startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '200'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN ---------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=200.00..301.98 rows=99 width=20) -(1 row) - --- Set custom tuple cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '2'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN ---------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=200.00..400.98 rows=99 width=20) -(1 row) - --- Update startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET fdw_startup_cost '2'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN -------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=2.00..202.98 rows=99 width=20) -(1 row) - --- Update startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET fdw_tuple_cost '0.5'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN ------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=2.00..54.48 rows=99 width=20) -(1 row) - --- Reset custom settings -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP fdw_startup_cost); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP fdw_tuple_cost); -EXPLAIN (COSTS) SELECT * FROM one_batch; - QUERY PLAN -------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on one_batch (cost=10000.00..10101.98 rows=99 width=20) -(1 row) - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/data_node.out b/tsl/test/expected/data_node.out deleted file mode 100644 index 10d92780744..00000000000 --- a/tsl/test/expected/data_node.out +++ /dev/null @@ -1,2307 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 -\set DN_DBNAME_4 :TEST_DBNAME _4 -\set DN_DBNAME_5 :TEST_DBNAME _5 -\set DN_DBNAME_6 :TEST_DBNAME _6 --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; --- Add data nodes using TimescaleDB data_node management API. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_1 | db_data_node_1 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', 'localhost', database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_2 | db_data_node_2 | t | t | t -(1 row) - -\set ON_ERROR_STOP 0 --- Add again -SELECT * FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated -ERROR: server "data_node_2" already exists --- No host provided -SELECT * FROM add_data_node('data_node_99'); -ERROR: function add_data_node(unknown) does not exist at character 15 -SELECT * FROM add_data_node(NULL); -ERROR: function add_data_node(unknown) does not exist at character 15 --- Add NULL data_node -SELECT * FROM add_data_node(NULL, host => 'localhost'); -WARNING: adding data node is deprecated -ERROR: data node name cannot be NULL -SELECT * FROM add_data_node(NULL, NULL); -WARNING: adding data node is deprecated -ERROR: a host needs to be specified --- Test invalid port numbers -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => 65536, - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated -ERROR: invalid port number 65536 -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => 0, - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated -ERROR: invalid port number 0 -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => -1, - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated -ERROR: invalid port number -1 -SELECT inet_server_port() as PGPORT \gset --- Adding a data node via ADD SERVER is blocked -CREATE SERVER data_node_4 FOREIGN DATA WRAPPER timescaledb_fdw -OPTIONS (host 'localhost', port ':PGPORT', dbname :'DN_DBNAME_4'); -ERROR: operation not supported for a TimescaleDB data node --- Dropping a data node via DROP SERVER is also blocked -DROP SERVER data_node_1, data_node_2; -ERROR: operation not supported on a TimescaleDB data node -\set ON_ERROR_STOP 1 --- Should not generate error with if_not_exists option -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2', - if_not_exists => true); -WARNING: adding data node is deprecated -NOTICE: data node "data_node_2" already exists, skipping - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_2 | db_data_node_2 | f | f | f -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_3 | db_data_node_3 | t | t | t -(1 row) - --- Altering the host, dbname, and port should work via ALTER SERVER -BEGIN; -ALTER SERVER data_node_3 OPTIONS (SET host 'data_node_3', SET dbname 'new_db_name', SET port '9999'); -SELECT srvname, srvoptions FROM pg_foreign_server WHERE srvname = 'data_node_3'; - srvname | srvoptions --------------+------------------------------------------------- - data_node_3 | {host=data_node_3,port=9999,dbname=new_db_name} -(1 row) - --- Altering the name should work -ALTER SERVER data_node_3 RENAME TO data_node_4; -SELECT srvname FROM pg_foreign_server WHERE srvname = 'data_node_4'; - srvname -------------- - data_node_4 -(1 row) - --- Revert name and options -ROLLBACK; -\set ON_ERROR_STOP 0 --- Should not be possible to set a version: -ALTER SERVER data_node_3 VERSION '2'; -ERROR: version not supported --- Should not be possible to set "available" -ALTER SERVER data_node_3 OPTIONS (SET available 'true'); -ERROR: cannot set "available" using ALTER SERVER -\set ON_ERROR_STOP 1 --- Make sure changing server owner is allowed -ALTER SERVER data_node_1 OWNER TO CURRENT_USER; --- List foreign data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 - data_node_3 -(3 rows) - -SELECT * FROM delete_data_node('data_node_3'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- List data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -\set ON_ERROR_STOP 0 --- Deleting a non-existing data node generates error -SELECT * FROM delete_data_node('data_node_3'); -WARNING: deleting data node is deprecated -ERROR: server "data_node_3" does not exist -\set ON_ERROR_STOP 1 --- Deleting non-existing data node with "if_exists" set does not generate error -SELECT * FROM delete_data_node('data_node_3', if_exists => true); -WARNING: deleting data node is deprecated -NOTICE: data node "data_node_3" does not exist, skipping - delete_data_node ------------------- - f -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -SELECT * FROM delete_data_node('data_node_1'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node('data_node_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- No data nodes left -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ------------ -(0 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+-------------+------------ -(0 rows) - --- Cleanup databases -RESET ROLE; -SET client_min_messages TO ERROR; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -SET client_min_messages TO INFO; -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_1 | db_data_node_1 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_2 | db_data_node_2 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_3 | db_data_node_3 | t | t | t -(1 row) - --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Create a distributed hypertable where no nodes can be selected --- because there are no data nodes with the right permissions. -CREATE TABLE disttable(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 -\set VERBOSITY default -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated -DETAIL: Multi-node is deprecated and will be removed in future releases. -NOTICE: 3 of 3 data nodes not used by this hypertable due to lack of permissions -HINT: Grant USAGE on data nodes to attach them to a hypertable. -ERROR: no data nodes can be assigned to the hypertable -DETAIL: Data nodes exist, but none have USAGE privilege. -HINT: Grant USAGE on data nodes to attach them to the hypertable. -\set VERBOSITY terse -\set ON_ERROR_STOP 1 -RESET ROLE; --- Allow ROLE_1 to create distributed tables on these data nodes. --- We'll test that data_node_3 is properly filtered when ROLE_1 --- creates a distributed hypertable without explicitly specifying --- data_node_2. -GRANT USAGE - ON FOREIGN SERVER data_node_1, data_node_2 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SELECT node_name - FROM timescaledb_information.data_nodes -ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 - data_node_3 -(3 rows) - -SELECT object_name, object_type, ARRAY_AGG(privilege_type) -FROM information_schema.role_usage_grants -WHERE object_schema NOT IN ('information_schema','pg_catalog') - AND object_type LIKE 'FOREIGN%' -GROUP BY object_schema, object_name, object_type -ORDER BY object_name, object_type; - object_name | object_type | array_agg ------------------+----------------------+--------------- - data_node_1 | FOREIGN SERVER | {USAGE,USAGE} - data_node_2 | FOREIGN SERVER | {USAGE,USAGE} - data_node_3 | FOREIGN SERVER | {USAGE} - timescaledb_fdw | FOREIGN DATA WRAPPER | {USAGE,USAGE} -(4 rows) - -SET ROLE :ROLE_1; --- Test that all data nodes are added to a hypertable and that the --- slices in the device dimension equals the number of data nodes. -BEGIN; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated -NOTICE: 1 of 3 data nodes not used by this hypertable due to lack of permissions -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE column_name = 'device'; - column_name | num_slices --------------+------------ - device | 2 -(1 row) - --- Dimension partitions should be created -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------- - disttable | 2 | -9223372036854775808 | {data_node_1} - disttable | 2 | 1073741823 | {data_node_2} -(2 rows) - --- All data nodes with USAGE should be added. -SELECT hdn.node_name -FROM _timescaledb_catalog.hypertable_data_node hdn, _timescaledb_catalog.hypertable h -WHERE h.table_name = 'disttable' AND hdn.hypertable_id = h.id; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -ROLLBACK; --- There should be an ERROR if we explicitly try to use a data node we --- don't have permission to use. -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', - data_nodes => '{ data_node_1, data_node_2, data_node_3 }'); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server data_node_3 -\set ON_ERROR_STOP 1 -RESET ROLE; --- Now let ROLE_1 use data_node_3 -GRANT USAGE - ON FOREIGN SERVER data_node_3 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Now specify less slices than there are data nodes to generate a --- warning -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | disttable | t -(1 row) - --- All data nodes should be added. -SELECT hdn.node_name -FROM _timescaledb_catalog.hypertable_data_node hdn, _timescaledb_catalog.hypertable h -WHERE h.table_name = 'disttable' AND hdn.hypertable_id = h.id; - node_name -------------- - data_node_1 - data_node_2 - data_node_3 -(3 rows) - --- Ensure that replication factor allows to distinguish data node hypertables from regular hypertables -SELECT replication_factor FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable'; - replication_factor --------------------- - 1 -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT replication_factor -FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable'; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_1]: SELECT replication_factor -FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable' -NOTICE: [data_node_1]: -replication_factor ------------------- - -1 -(1 row) - - -NOTICE: [data_node_2]: SELECT replication_factor -FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable' -NOTICE: [data_node_2]: -replication_factor ------------------- - -1 -(1 row) - - -NOTICE: [data_node_3]: SELECT replication_factor -FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable' -NOTICE: [data_node_3]: -replication_factor ------------------- - -1 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Create one chunk -INSERT INTO disttable VALUES ('2019-02-02 10:45', 1, 23.4); --- Chunk mapping created -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 - data_node_3 -(3 rows) - -DROP TABLE disttable; --- data node mappings should be cleaned up -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-----------+-------------- -(0 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+-------------+------------ -(0 rows) - --- Now create tables as cluster user -CREATE TABLE disttable(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- Attach data node should fail when called on a non-hypertable -SELECT * FROM attach_data_node('data_node_1', 'disttable'); -WARNING: attaching data node is deprecated -ERROR: table "disttable" is not a hypertable --- Test some bad create_hypertable() parameter values for distributed hypertables --- Bad replication factor -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 0, data_nodes => '{ "data_node_2", "data_node_4" }'); -WARNING: distributed hypertable is deprecated -ERROR: invalid replication factor -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 32768); -WARNING: distributed hypertable is deprecated -ERROR: replication factor too large for hypertable "disttable" -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => -1); -ERROR: invalid replication factor -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => -1); -WARNING: distributed hypertable is deprecated -ERROR: invalid replication factor --- Non-existing data node -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 2, data_nodes => '{ "data_node_4" }'); -WARNING: distributed hypertable is deprecated -ERROR: server "data_node_4" does not exist -\set ON_ERROR_STOP 1 --- Use a subset of data nodes and a replication factor of two so that --- each chunk is associated with more than one data node. Set --- number_partitions lower than number of servers to raise a warning -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', number_partitions => 1, replication_factor => 2, data_nodes => '{ "data_node_2", "data_node_3" }'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 3 | public | disttable | t -(1 row) - --- Create some chunks -INSERT INTO disttable VALUES - ('2019-02-02 10:45', 1, 23.4), - ('2019-05-23 10:45', 4, 14.9), - ('2019-07-23 10:45', 8, 7.6); -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace ----------------------------------------------+------------ - _timescaledb_internal._dist_hyper_3_2_chunk | - _timescaledb_internal._dist_hyper_3_3_chunk | - _timescaledb_internal._dist_hyper_3_4_chunk | -(3 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 2 | 3 | _timescaledb_internal | _dist_hyper_3_2_chunk | | f | 0 | f - 3 | 3 | _timescaledb_internal | _dist_hyper_3_3_chunk | | f | 0 | f - 4 | 3 | _timescaledb_internal | _dist_hyper_3_4_chunk | | f | 0 | f -(3 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 3 | 3 | data_node_2 | f - 3 | 2 | data_node_3 | f -(2 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+------------- - 2 | 1 | data_node_2 - 2 | 1 | data_node_3 - 3 | 2 | data_node_2 - 3 | 2 | data_node_3 - 4 | 3 | data_node_2 - 4 | 3 | data_node_3 -(6 rows) - --- Dropping a chunk should also clean up data node mappings -SELECT * FROM drop_chunks('disttable', older_than => '2019-05-22 17:18'::timestamptz); - drop_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_3_2_chunk -(1 row) - -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace ----------------------------------------------+------------ - _timescaledb_internal._dist_hyper_3_3_chunk | - _timescaledb_internal._dist_hyper_3_4_chunk | -(2 rows) - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name ------------------------+--------------------- - _dist_hyper_3_3_chunk | data_node_2 - _dist_hyper_3_4_chunk | data_node_2 -(2 rows) - -SELECT table_name, node_name -FROM _timescaledb_catalog.chunk c, -_timescaledb_catalog.chunk_data_node cdn -WHERE c.id = cdn.chunk_id; - table_name | node_name ------------------------+------------- - _dist_hyper_3_3_chunk | data_node_2 - _dist_hyper_3_3_chunk | data_node_3 - _dist_hyper_3_4_chunk | data_node_2 - _dist_hyper_3_4_chunk | data_node_3 -(4 rows) - --- Setting the same data node should do nothing and return false -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_3'); - set_chunk_default_data_node ------------------------------ - t -(1 row) - --- Should update the default data node and return true -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_2'); - set_chunk_default_data_node ------------------------------ - t -(1 row) - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name ------------------------+--------------------- - _dist_hyper_3_3_chunk | data_node_2 - _dist_hyper_3_4_chunk | data_node_2 -(2 rows) - --- Reset the default data node -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_3'); - set_chunk_default_data_node ------------------------------ - t -(1 row) - -\set ON_ERROR_STOP 0 --- Will fail because data_node_2 contains chunks -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_2'); -WARNING: deleting data node is deprecated -ERROR: data node "data_node_2" still holds data for distributed hypertable "disttable" --- non-existing chunk -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('x_chunk', 'data_node_3'); -ERROR: relation "x_chunk" does not exist at character 66 --- non-existing data node -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_0000'); -ERROR: server "data_node_0000" does not exist --- data node exists but does not store the chunk -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_1'); -ERROR: chunk "_dist_hyper_3_3_chunk" does not exist on data node "data_node_1" --- NULL try -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node(NULL, 'data_node_3'); -ERROR: invalid chunk: cannot be NULL -\set ON_ERROR_STOP 1 --- Deleting a data node removes the "foreign" chunk table(s) that --- reference that data node as "primary" and should also remove the --- hypertable_data_node and chunk_data_node mappings for that data --- node. In the future we might want to fallback to a replica data --- node for those chunks that have multiple data nodes so that the --- chunk is not removed unnecessarily. We use force => true b/c --- data_node_2 contains chunks. Dimension partitions should also be --- updated to reflect the loss of the data node. -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------------------- - disttable | 6 | -9223372036854775808 | {data_node_2,data_node_3} -(1 row) - -SELECT * FROM delete_data_node('data_node_2', force => true); -WARNING: deleting data node is deprecated -WARNING: distributed hypertable "disttable" is under-replicated -WARNING: insufficient number of data nodes for distributed hypertable "disttable" - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------- - disttable | 6 | -9223372036854775808 | {data_node_3} -(1 row) - -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace ----------------------------------------------+------------ - _timescaledb_internal._dist_hyper_3_3_chunk | - _timescaledb_internal._dist_hyper_3_4_chunk | -(2 rows) - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name ------------------------+--------------------- - _dist_hyper_3_3_chunk | data_node_3 - _dist_hyper_3_4_chunk | data_node_3 -(2 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 3 | 3 | _timescaledb_internal | _dist_hyper_3_3_chunk | | f | 0 | f - 4 | 3 | _timescaledb_internal | _dist_hyper_3_4_chunk | | f | 0 | f -(2 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 3 | 2 | data_node_3 | f -(1 row) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+------------- - 3 | 2 | data_node_3 - 4 | 3 | data_node_3 -(2 rows) - -\set ON_ERROR_STOP 0 --- can't delete b/c it's last data replica -SELECT * FROM delete_data_node('data_node_3', force => true); -WARNING: deleting data node is deprecated -ERROR: insufficient number of data nodes -\set ON_ERROR_STOP 1 --- Removing all data allows us to delete the data node by force, but --- with WARNING that new data will be under-replicated -TRUNCATE disttable; -SELECT * FROM delete_data_node('data_node_3', force => true); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "disttable" - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace --------+------------ -(0 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-----------+-------------- -(0 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-------------+------------+---------------------+---------+--------+----------- -(0 rows) - --- Attach data node should now succeed -SET client_min_messages TO NOTICE; -SELECT * FROM attach_data_node('data_node_1', 'disttable'); -WARNING: attaching data node is deprecated - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+------------- - 3 | 3 | data_node_1 -(1 row) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 3 | 3 | data_node_1 | f -(1 row) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1'); - ping_data_node ----------------- - t -(1 row) - --- Ensure timeout returned by argument -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '0s'); - ping_data_node ----------------- - f -(1 row) - -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '3s'); - ping_data_node ----------------- - t -(1 row) - -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '1 day'); - ping_data_node ----------------- - t -(1 row) - --- Create data node referencing postgres_fdw -RESET ROLE; -CREATE EXTENSION postgres_fdw; -CREATE SERVER pg_server_1 FOREIGN DATA WRAPPER postgres_fdw; -SET ROLE :ROLE_1; -CREATE TABLE standalone(time TIMESTAMPTZ, device INT, value FLOAT); -SELECT * FROM create_hypertable('standalone','time'); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 4 | public | standalone | t -(1 row) - -\set ON_ERROR_STOP 0 --- Throw ERROR for non-existing data node -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_123456789'); -ERROR: server "data_node_123456789" does not exist --- ERROR on NULL -SELECT * FROM _timescaledb_functions.ping_data_node(NULL); -ERROR: data node name cannot be NULL --- ERROR when not passing TimescaleDB data node -SELECT * FROM _timescaledb_functions.ping_data_node('pg_data_node_1'); -ERROR: server "pg_data_node_1" does not exist --- ERROR on attaching to non-distributed hypertable -SELECT * FROM attach_data_node('data_node_1', 'standalone'); -WARNING: attaching data node is deprecated -ERROR: hypertable "standalone" is not distributed -\set ON_ERROR_STOP 1 -DROP TABLE standalone; --- Some attach data node error cases -\set ON_ERROR_STOP 0 --- Invalid arguments -SELECT * FROM attach_data_node('data_node_1', NULL, true); -WARNING: attaching data node is deprecated -ERROR: hypertable cannot be NULL -SELECT * FROM attach_data_node(NULL, 'disttable', true); -WARNING: attaching data node is deprecated -ERROR: data node name cannot be NULL --- Deleted data node -SELECT * FROM attach_data_node('data_node_2', 'disttable'); -WARNING: attaching data node is deprecated -ERROR: server "data_node_2" does not exist --- Attaching to an already attached data node without 'if_not_exists' -SELECT * FROM attach_data_node('data_node_1', 'disttable', false); -WARNING: attaching data node is deprecated -ERROR: data node "data_node_1" is already attached to hypertable "disttable" --- Attaching a data node to another data node -\c :DN_DBNAME_1 -SELECT * FROM attach_data_node('data_node_4', 'disttable'); -WARNING: attaching data node is deprecated -ERROR: hypertable "disttable" is not distributed -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 1 --- Attach if not exists -SELECT * FROM attach_data_node('data_node_1', 'disttable', true); -WARNING: attaching data node is deprecated -NOTICE: data node "data_node_1" is already attached to hypertable "disttable", skipping - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+------------- - 3 | 3 | data_node_1 -(1 row) - --- Should repartition too. First show existing number of slices in --- 'device' dimension -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE num_slices IS NOT NULL -AND column_name = 'device'; - column_name | num_slices --------------+------------ - device | 1 -(1 row) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_4', host => 'localhost', database => :'DN_DBNAME_4', - if_not_exists => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_4 | db_data_node_4 | t | t | t -(1 row) - --- Now let ROLE_1 use data_node_4 since it owns this "disttable" -GRANT USAGE - ON FOREIGN SERVER data_node_4 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SELECT * FROM attach_data_node('data_node_4', 'disttable'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "device" was increased to 2 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+------------- - 3 | 1 | data_node_4 -(1 row) - --- Recheck that ownership on data_node_4 is proper -SELECT * FROM test.remote_exec(NULL, $$ SELECT tablename, tableowner from pg_catalog.pg_tables where tablename = 'disttable'; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_1]: SELECT tablename, tableowner from pg_catalog.pg_tables where tablename = 'disttable' -NOTICE: [data_node_1]: -tablename|tableowner ----------+----------- -disttable|test_role_1 -(1 row) - - -NOTICE: [data_node_4]: SELECT tablename, tableowner from pg_catalog.pg_tables where tablename = 'disttable' -NOTICE: [data_node_4]: -tablename|tableowner ----------+----------- -disttable|test_role_1 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Show updated number of slices in 'device' dimension. -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE num_slices IS NOT NULL -AND column_name = 'device'; - column_name | num_slices --------------+------------ - device | 2 -(1 row) - --- Clean up -DROP TABLE disttable; -SELECT * FROM delete_data_node('data_node_4'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SET ROLE :ROLE_1; --- Creating a distributed hypertable without any servers should fail -CREATE TABLE disttable(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- Creating a distributed hypertable without any data nodes should fail -SELECT * FROM create_distributed_hypertable('disttable', 'time', data_nodes => '{ }'); -WARNING: distributed hypertable is deprecated -ERROR: no data nodes can be assigned to the hypertable -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_1'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ------------ -(0 rows) - -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace --------+------------ -(0 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-----------+-------------- -(0 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-------------+------------+---------------------+---------+--------+----------- -(0 rows) - -\set ON_ERROR_STOP 0 --- No data nodes remain, so should fail -SELECT * FROM create_distributed_hypertable('disttable', 'time'); -WARNING: distributed hypertable is deprecated -ERROR: no data nodes can be assigned to the hypertable -\set ON_ERROR_STOP 1 --- These data nodes have been deleted, so safe to remove their databases. -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -DROP DATABASE :DN_DBNAME_4 WITH (FORCE); --- there should be no data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ------------ -(0 rows) - --- let's add some -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_1 | db_data_node_1 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_2 | db_data_node_2 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_3 | db_data_node_3 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -DROP TABLE disttable; -CREATE TABLE disttable(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 2, - replication_factor => 2, - data_nodes => '{"data_node_1", "data_node_2", "data_node_3"}'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 5 | public | disttable | t -(1 row) - --- Create some chunks on all the data_nodes -INSERT INTO disttable VALUES - ('2019-02-02 10:45', 1, 23.4), - ('2019-05-23 10:45', 4, 14.9), - ('2019-07-23 10:45', 8, 7.6); -SELECT * FROM test.show_subtables('disttable'); - Child | Tablespace ----------------------------------------------+------------ - _timescaledb_internal._dist_hyper_5_5_chunk | - _timescaledb_internal._dist_hyper_5_6_chunk | - _timescaledb_internal._dist_hyper_5_7_chunk | -(3 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 5 | 5 | _timescaledb_internal | _dist_hyper_5_5_chunk | | f | 0 | f - 6 | 5 | _timescaledb_internal | _dist_hyper_5_6_chunk | | f | 0 | f - 7 | 5 | _timescaledb_internal | _dist_hyper_5_7_chunk | | f | 0 | f -(3 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 5 | 1 | data_node_1 | f - 5 | 1 | data_node_2 | f - 5 | 1 | data_node_3 | f -(3 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+------------- - 5 | 1 | data_node_1 - 5 | 1 | data_node_2 - 6 | 2 | data_node_2 - 6 | 1 | data_node_3 - 7 | 2 | data_node_1 - 7 | 3 | data_node_2 -(6 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_1,data_node_2} - disttable | 9 | 1073741823 | {data_node_2,data_node_3} -(2 rows) - --- Add additional hypertable -CREATE TABLE disttable_2(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_2', 'time', 'device', 2, replication_factor => 2, data_nodes => '{"data_node_1", "data_node_2", "data_node_3"}'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 6 | public | disttable_2 | t -(1 row) - -CREATE TABLE devices(device int, name text); -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 5 | 1 | data_node_1 | f - 5 | 1 | data_node_2 | f - 5 | 1 | data_node_3 | f - 6 | 2 | data_node_1 | f - 6 | 2 | data_node_2 | f - 6 | 2 | data_node_3 | f -(6 rows) - --- Block one data node for specific hypertable -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', 'disttable'); - block_new_chunks ------------------- - 1 -(1 row) - --- Block one data node for all hypertables -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1'); -NOTICE: new chunks already blocked on data node "data_node_1" for hypertable "disttable" - block_new_chunks ------------------- - 1 -(1 row) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 5 | 1 | data_node_2 | f - 5 | 1 | data_node_3 | f - 6 | 2 | data_node_2 | f - 6 | 2 | data_node_3 | f - 5 | 1 | data_node_1 | t - 6 | 2 | data_node_1 | t -(6 rows) - --- insert more data -INSERT INTO disttable VALUES - ('2019-08-02 10:45', 1, 14.4), - ('2019-08-15 10:45', 4, 14.9), - ('2019-08-26 10:45', 8, 17.6); --- no new chunks on data_node_1 -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+------------- - 5 | 1 | data_node_1 - 5 | 1 | data_node_2 - 6 | 2 | data_node_2 - 6 | 1 | data_node_3 - 7 | 2 | data_node_1 - 7 | 3 | data_node_2 - 8 | 4 | data_node_2 - 8 | 2 | data_node_3 - 9 | 3 | data_node_3 - 9 | 5 | data_node_2 - 10 | 6 | data_node_2 - 10 | 4 | data_node_3 -(12 rows) - --- some ERROR cases -\set ON_ERROR_STOP 0 --- Will error due to under-replication -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_2'); -ERROR: insufficient number of data nodes for distributed hypertable "disttable" --- can't block/allow non-existing data node -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_12345', 'disttable'); -ERROR: server "data_node_12345" does not exist -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_12345', 'disttable'); -ERROR: server "data_node_12345" does not exist --- NULL data node -SELECT * FROM timescaledb_experimental.block_new_chunks(NULL, 'disttable'); -ERROR: data node name cannot be NULL -SELECT * FROM timescaledb_experimental.allow_new_chunks(NULL, 'disttable'); -ERROR: data node name cannot be NULL --- can't block/allow on non hypertable -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', 'devices'); -ERROR: table "devices" is not a hypertable -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_1', 'devices'); -ERROR: table "devices" is not a hypertable -\set ON_ERROR_STOP 1 --- Force block all data nodes. Dimension partition information should --- be updated to elide blocked data nodes -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_2,data_node_3} - disttable | 9 | 1073741823 | {data_node_3,data_node_2} - disttable_2 | 11 | -9223372036854775808 | {data_node_2,data_node_3} - disttable_2 | 11 | 1073741823 | {data_node_3,data_node_2} -(4 rows) - -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_2', force => true); -WARNING: insufficient number of data nodes for distributed hypertable "disttable" -WARNING: insufficient number of data nodes for distributed hypertable "disttable_2" - block_new_chunks ------------------- - 2 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------- - disttable | 9 | -9223372036854775808 | {data_node_3} - disttable | 9 | 1073741823 | {data_node_3} - disttable_2 | 11 | -9223372036854775808 | {data_node_3} - disttable_2 | 11 | 1073741823 | {data_node_3} -(4 rows) - -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', force => true); -NOTICE: new chunks already blocked on data node "data_node_1" for hypertable "disttable" -NOTICE: new chunks already blocked on data node "data_node_1" for hypertable "disttable_2" - block_new_chunks ------------------- - 0 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------- - disttable | 9 | -9223372036854775808 | {data_node_3} - disttable | 9 | 1073741823 | {data_node_3} - disttable_2 | 11 | -9223372036854775808 | {data_node_3} - disttable_2 | 11 | 1073741823 | {data_node_3} -(4 rows) - -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_3', force => true); -WARNING: insufficient number of data nodes for distributed hypertable "disttable" -WARNING: insufficient number of data nodes for distributed hypertable "disttable_2" - block_new_chunks ------------------- - 2 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+------------ - disttable | 9 | -9223372036854775808 | - disttable | 9 | 1073741823 | - disttable_2 | 11 | -9223372036854775808 | - disttable_2 | 11 | 1073741823 | -(4 rows) - --- All data nodes are blocked -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+-------------+-------------- - 5 | 1 | data_node_1 | t - 6 | 2 | data_node_1 | t - 5 | 1 | data_node_2 | t - 6 | 2 | data_node_2 | t - 5 | 1 | data_node_3 | t - 6 | 2 | data_node_3 | t -(6 rows) - -\set ON_ERROR_STOP 0 --- insert should fail b/c all data nodes are blocked -INSERT INTO disttable VALUES ('2019-11-02 02:45', 1, 13.3); -ERROR: insufficient number of data nodes -\set ON_ERROR_STOP 1 --- unblock data nodes for all hypertables -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_1'); - allow_new_chunks ------------------- - 2 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------- - disttable | 9 | -9223372036854775808 | {data_node_1} - disttable | 9 | 1073741823 | {data_node_1} - disttable_2 | 11 | -9223372036854775808 | {data_node_1} - disttable_2 | 11 | 1073741823 | {data_node_1} -(4 rows) - -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_2'); - allow_new_chunks ------------------- - 2 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_1,data_node_2} - disttable | 9 | 1073741823 | {data_node_2,data_node_1} - disttable_2 | 11 | -9223372036854775808 | {data_node_1,data_node_2} - disttable_2 | 11 | 1073741823 | {data_node_2,data_node_1} -(4 rows) - -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_3'); - allow_new_chunks ------------------- - 2 -(1 row) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_1,data_node_2} - disttable | 9 | 1073741823 | {data_node_2,data_node_3} - disttable_2 | 11 | -9223372036854775808 | {data_node_1,data_node_2} - disttable_2 | 11 | 1073741823 | {data_node_2,data_node_3} -(4 rows) - -SELECT table_name, node_name, block_chunks -FROM _timescaledb_catalog.hypertable_data_node dn, -_timescaledb_catalog.hypertable h -WHERE dn.hypertable_id = h.id -ORDER BY table_name; - table_name | node_name | block_chunks --------------+-------------+-------------- - disttable | data_node_1 | f - disttable | data_node_2 | f - disttable | data_node_3 | f - disttable_2 | data_node_1 | f - disttable_2 | data_node_2 | f - disttable_2 | data_node_3 | f -(6 rows) - --- Detach should work b/c disttable_2 has no data and more data nodes --- than replication factor -SELECT * FROM detach_data_node('data_node_2', 'disttable_2'); -WARNING: detaching data node is deprecated - detach_data_node ------------------- - 1 -(1 row) - -\set ON_ERROR_STOP 0 --- can't detach non-existing data node -SELECT * FROM detach_data_node('data_node_12345', 'disttable'); -WARNING: detaching data node is deprecated -ERROR: server "data_node_12345" does not exist --- NULL data node -SELECT * FROM detach_data_node(NULL, 'disttable'); -WARNING: detaching data node is deprecated -ERROR: data node name cannot be NULL --- Can't detach data node_1 b/c it contains data for disttable -SELECT * FROM detach_data_node('data_node_1'); -WARNING: detaching data node is deprecated -ERROR: data node "data_node_1" still holds data for distributed hypertable "disttable" --- can't detach already detached data node -SELECT * FROM detach_data_node('data_node_2', 'disttable_2'); -WARNING: detaching data node is deprecated -ERROR: data node "data_node_2" is not attached to hypertable "disttable_2" -SELECT * FROM detach_data_node('data_node_2', 'disttable_2', if_attached => false); -WARNING: detaching data node is deprecated -ERROR: data node "data_node_2" is not attached to hypertable "disttable_2" --- can't detach b/c of replication factor for disttable_2 -SELECT * FROM detach_data_node('data_node_3', 'disttable_2'); -WARNING: detaching data node is deprecated -ERROR: insufficient number of data nodes for distributed hypertable "disttable_2" --- can't detach non hypertable -SELECT * FROM detach_data_node('data_node_3', 'devices'); -WARNING: detaching data node is deprecated -ERROR: table "devices" is not a hypertable -\set ON_ERROR_STOP 1 --- do nothing if node is not attached -SELECT * FROM detach_data_node('data_node_2', 'disttable_2', if_attached => true); -WARNING: detaching data node is deprecated -NOTICE: data node "data_node_2" is not attached to hypertable "disttable_2", skipping - detach_data_node ------------------- - 0 -(1 row) - --- force detach data node to become under-replicated for new data -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_1,data_node_2} - disttable | 9 | 1073741823 | {data_node_2,data_node_3} - disttable_2 | 11 | -9223372036854775808 | {data_node_1,data_node_3} - disttable_2 | 11 | 1073741823 | {data_node_3,data_node_1} -(4 rows) - -SELECT * FROM detach_data_node('data_node_3', 'disttable_2', force => true); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "disttable_2" -NOTICE: the number of partitions in dimension "device" of hypertable "disttable_2" was decreased to 1 - detach_data_node ------------------- - 1 -(1 row) - --- Dimension partitions should be updated to no longer list the data --- node for the hypertable -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes --------------+--------------+----------------------+--------------------------- - disttable | 9 | -9223372036854775808 | {data_node_1,data_node_2} - disttable | 9 | 1073741823 | {data_node_2,data_node_3} - disttable_2 | 11 | -9223372036854775808 | {data_node_1} -(3 rows) - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name -------------------------+--------------------- - _dist_hyper_5_10_chunk | data_node_2 - _dist_hyper_5_5_chunk | data_node_1 - _dist_hyper_5_6_chunk | data_node_2 - _dist_hyper_5_7_chunk | data_node_1 - _dist_hyper_5_8_chunk | data_node_2 - _dist_hyper_5_9_chunk | data_node_3 -(6 rows) - --- force detach data node with data -SELECT * FROM detach_data_node('data_node_3', 'disttable', force => true); -WARNING: detaching data node is deprecated -WARNING: distributed hypertable "disttable" is under-replicated - detach_data_node ------------------- - 1 -(1 row) - --- chunk and hypertable metadata should be deleted as well -SELECT * FROM _timescaledb_catalog.chunk_data_node; - chunk_id | node_chunk_id | node_name -----------+---------------+------------- - 5 | 1 | data_node_1 - 5 | 1 | data_node_2 - 6 | 2 | data_node_2 - 7 | 2 | data_node_1 - 7 | 3 | data_node_2 - 8 | 4 | data_node_2 - 9 | 5 | data_node_2 - 10 | 6 | data_node_2 -(8 rows) - -SELECT table_name, node_name, block_chunks -FROM _timescaledb_catalog.hypertable_data_node dn, -_timescaledb_catalog.hypertable h -WHERE dn.hypertable_id = h.id -ORDER BY table_name; - table_name | node_name | block_chunks --------------+-------------+-------------- - disttable | data_node_1 | f - disttable | data_node_2 | f - disttable_2 | data_node_1 | f -(3 rows) - --- detached data_node_3 should not show up any more -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name -------------------------+--------------------- - _dist_hyper_5_10_chunk | data_node_2 - _dist_hyper_5_5_chunk | data_node_1 - _dist_hyper_5_6_chunk | data_node_2 - _dist_hyper_5_7_chunk | data_node_1 - _dist_hyper_5_8_chunk | data_node_2 - _dist_hyper_5_9_chunk | data_node_2 -(6 rows) - -\set ON_ERROR_STOP 0 --- detaching data node with last data replica should ERROR even when forcing -SELECT * FROM detach_data_node('server_2', 'disttable', force => true); -WARNING: detaching data node is deprecated -ERROR: server "server_2" does not exist -\set ON_ERROR_STOP 1 --- drop all chunks -SELECT * FROM drop_chunks('disttable', older_than => '2200-01-01 00:00'::timestamptz); - drop_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_5_5_chunk - _timescaledb_internal._dist_hyper_5_6_chunk - _timescaledb_internal._dist_hyper_5_7_chunk - _timescaledb_internal._dist_hyper_5_8_chunk - _timescaledb_internal._dist_hyper_5_9_chunk - _timescaledb_internal._dist_hyper_5_10_chunk -(6 rows) - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - foreign_table_name | foreign_server_name ---------------------+--------------------- -(0 rows) - -SELECT * FROM detach_data_node('data_node_2', 'disttable', force => true); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "disttable" -NOTICE: the number of partitions in dimension "device" of hypertable "disttable" was decreased to 1 - detach_data_node ------------------- - 1 -(1 row) - --- Let's add more data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_4', host => 'localhost', database => :'DN_DBNAME_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_4 | db_data_node_4 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_5', host => 'localhost', database => :'DN_DBNAME_5'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_5 | db_data_node_5 | t | t | t -(1 row) - -GRANT ALL ON FOREIGN SERVER data_node_4, data_node_5 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Create table as super user -SET ROLE :ROLE_SUPERUSER; -CREATE TABLE disttable_3(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_3', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5"}'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 7 | public | disttable_3 | t -(1 row) - -SET ROLE :ROLE_1; -CREATE TABLE disttable_4(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_4', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5"}'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 8 | public | disttable_4 | t -(1 row) - -\set ON_ERROR_STOP 0 --- error due to missing permissions -SELECT * FROM detach_data_node('data_node_4', 'disttable_3'); -WARNING: detaching data node is deprecated -ERROR: must be owner of hypertable "disttable_3" -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_4', 'disttable_3'); -ERROR: must be owner of hypertable "disttable_3" -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_4', 'disttable_3'); -ERROR: must be owner of hypertable "disttable_3" -\set ON_ERROR_STOP 1 --- detach table(s) where user has permissions, otherwise show --- NOTICE. Drop hypertables on data nodes in the process. Drop a --- hypertable on a data node manually to ensure the command can handle --- non-existing hypertables. -CREATE TABLE disttable_5(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_5', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5" }'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 9 | public | disttable_5 | t -(1 row) - -SELECT * FROM test.remote_exec('{ data_node_4 }', $$ SELECT hypertable_name, owner FROM timescaledb_information.hypertables; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_4]: SELECT hypertable_name, owner FROM timescaledb_information.hypertables -NOTICE: [data_node_4]: -hypertable_name|owner ----------------+----------- -disttable_3 |super_user -disttable_4 |test_role_1 -disttable_5 |test_role_1 -(3 rows) - - - remote_exec -------------- - -(1 row) - -CALL distributed_exec($$ DROP TABLE disttable_4 $$, '{ data_node_4 }'); -RESET ROLE; -CALL distributed_exec(format('ALTER TABLE disttable_5 OWNER TO %s', :'ROLE_CLUSTER_SUPERUSER'), '{ data_node_4 }'); -SET ROLE :ROLE_1; --- test first detach without permission to drop the remote data -\set ON_ERROR_STOP 0 -SELECT * FROM detach_data_node('data_node_4', drop_remote_data => true); -WARNING: detaching data node is deprecated -NOTICE: skipping hypertable "disttable_3" due to missing permissions -ERROR: [data_node_4]: must be owner of table disttable_5 -\set ON_ERROR_STOP 1 --- detach should work with permissions -RESET ROLE; -CALL distributed_exec(format('ALTER TABLE disttable_5 OWNER TO %s', :'ROLE_1'), '{ data_node_4 }'); -SET ROLE :ROLE_1; -SELECT * FROM detach_data_node('data_node_4', drop_remote_data => true); -WARNING: detaching data node is deprecated -NOTICE: skipping hypertable "disttable_3" due to missing permissions - detach_data_node ------------------- - 2 -(1 row) - --- Hypertables user had permissions for should be dropped on data nodes -SELECT * FROM test.remote_exec('{ data_node_4 }', $$ SELECT hypertable_name, owner FROM timescaledb_information.hypertables; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_4]: SELECT hypertable_name, owner FROM timescaledb_information.hypertables -NOTICE: [data_node_4]: -hypertable_name|owner ----------------+---------- -disttable_3 |super_user -(1 row) - - - remote_exec -------------- - -(1 row) - --- Cleanup -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_1', force =>true); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "disttable" -WARNING: insufficient number of data nodes for distributed hypertable "disttable_2" - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node('data_node_2', force =>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node('data_node_3', force =>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Cannot delete a data node which is attached to a table that we don't --- have owner permissions on -SELECT * FROM delete_data_node('data_node_4', force =>true); -WARNING: deleting data node is deprecated -ERROR: permission denied for hypertable "disttable_3" -SELECT * FROM delete_data_node('data_node_5', force =>true); -WARNING: deleting data node is deprecated -ERROR: permission denied for hypertable "disttable_3" -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_CLUSTER_SUPERUSER; -DROP TABLE disttable_3; --- Now we should be able to delete the data nodes -SELECT * FROM delete_data_node('data_node_4', force =>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node('data_node_5', force =>true); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "disttable_4" -WARNING: insufficient number of data nodes for distributed hypertable "disttable_5" - delete_data_node ------------------- - t -(1 row) - -\set ON_ERROR_STOP 0 --- Should fail because host has to be provided. -SELECT * FROM add_data_node('data_node_6'); -ERROR: function add_data_node(unknown) does not exist at character 15 -\set ON_ERROR_STOP 1 --- --- Test timescale extension version check during add_data_node() --- and create_distributed_hypertable() calls. --- --- Use mock extension and create basic function wrappers to --- establish connection to a data node. --- -RESET ROLE; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -CREATE DATABASE :DN_DBNAME_1 OWNER :ROLE_1; -\c :DN_DBNAME_1 -CREATE SCHEMA _timescaledb_functions; -GRANT ALL ON SCHEMA _timescaledb_functions TO :ROLE_1; -CREATE FUNCTION _timescaledb_functions.set_dist_id(uuid UUID) - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; -CREATE FUNCTION _timescaledb_functions.set_peer_dist_id(uuid UUID) - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; -CREATE FUNCTION _timescaledb_functions.validate_as_data_node() - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; -CREATE EXTENSION timescaledb VERSION '0.0.0'; -\c :TEST_DBNAME :ROLE_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT * FROM add_data_node('data_node_1', 'localhost', database => :'DN_DBNAME_1', - bootstrap => false); -WARNING: adding data node is deprecated -ERROR: remote PostgreSQL instance has an incompatible timescaledb extension version --- Testing that it is not possible to use oneself as a data node. This --- is not allowed since it would create a cycle. --- --- We need to use the same owner for this connection as the extension --- owner here to avoid triggering another error. --- --- We cannot use default verbosity here for debugging since the --- version number is printed in some of the notices. -SELECT * FROM add_data_node('data_node_99', host => 'localhost'); -WARNING: adding data node is deprecated -NOTICE: database "db_data_node" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: [data_node_99]: cannot add the current database as a data node to itself -\set ON_ERROR_STOP 1 --- Test adding bootstrapped data node where extension owner is different from user adding a data node -SET ROLE :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE :DN_DBNAME_6; -\c :DN_DBNAME_6 -SET client_min_messages = ERROR; --- Creating an extension as superuser -CREATE EXTENSION timescaledb; -RESET client_min_messages; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_3; --- Trying to add data node as non-superuser without GRANT on the --- foreign data wrapper will fail. -\set ON_ERROR_STOP 0 -SELECT * FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6'); -WARNING: adding data node is deprecated -ERROR: permission denied for foreign-data wrapper timescaledb_fdw -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- ROLE_3 doesn't have a password in the passfile and has not way to --- authenticate so adding a data node will still fail. -SELECT * FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6'); -WARNING: adding data node is deprecated -ERROR: could not connect to "data_node_6" -\set ON_ERROR_STOP 1 --- Providing the password on the command line should work -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6', password => :'ROLE_3_PASS'); -WARNING: adding data node is deprecated -NOTICE: database "db_data_node_6" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_6 | db_data_node_6 | t | f | f -(1 row) - -SELECT * FROM delete_data_node('data_node_6'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -RESET ROLE; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -DROP DATABASE :DN_DBNAME_4 WITH (FORCE); -DROP DATABASE :DN_DBNAME_5 WITH (FORCE); -DROP DATABASE :DN_DBNAME_6 WITH (FORCE); ------------------------------------------------ --- Test alter_data_node() ------------------------------------------------ -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_1 | db_data_node_1 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_2 | db_data_node_2 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+----------------+--------------+------------------+------------------- - data_node_3 | db_data_node_3 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE hyper1 (time timestamptz, location int, temp float); -CREATE TABLE hyper2 (LIKE hyper1); -CREATE TABLE hyper3 (LIKE hyper1); -CREATE TABLE hyper_1dim (LIKE hyper1); -SELECT create_distributed_hypertable('hyper1', 'time', 'location', replication_factor=>1); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (10,public,hyper1,t) -(1 row) - -SELECT create_distributed_hypertable('hyper2', 'time', 'location', replication_factor=>2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (11,public,hyper2,t) -(1 row) - -SELECT create_distributed_hypertable('hyper3', 'time', 'location', replication_factor=>3); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (12,public,hyper3,t) -(1 row) - -SELECT create_distributed_hypertable('hyper_1dim', 'time', chunk_time_interval=>interval '2 days', replication_factor=>3); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (13,public,hyper_1dim,t) -(1 row) - -SELECT setseed(1); - setseed ---------- - -(1 row) - -INSERT INTO hyper1 -SELECT t, (abs(timestamp_hash(t::timestamp)) % 3) + 1, random() * 30 -FROM generate_series('2022-01-01 00:00:00'::timestamptz, '2022-01-05 00:00:00', '1 h') t; -INSERT INTO hyper2 SELECT * FROM hyper1; -INSERT INTO hyper3 SELECT * FROM hyper1; -INSERT INTO hyper_1dim SELECT * FROM hyper1; --- create view to see the data nodes and default data node of all --- chunks -CREATE VIEW chunk_query_data_node AS -SELECT ch.hypertable_name, format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass AS chunk, ch.data_nodes, fs.srvname default_data_node - FROM timescaledb_information.chunks ch - INNER JOIN pg_foreign_table ft ON (format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass = ft.ftrelid) - INNER JOIN pg_foreign_server fs ON (ft.ftserver = fs.oid) - ORDER BY 1, 2; -SELECT * FROM chunk_query_data_node; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper1 | _timescaledb_internal._dist_hyper_10_12_chunk | {data_node_1} | data_node_1 - hyper1 | _timescaledb_internal._dist_hyper_10_13_chunk | {data_node_2} | data_node_2 - hyper1 | _timescaledb_internal._dist_hyper_10_14_chunk | {data_node_3} | data_node_3 - hyper2 | _timescaledb_internal._dist_hyper_11_15_chunk | {data_node_1,data_node_2} | data_node_1 - hyper2 | _timescaledb_internal._dist_hyper_11_16_chunk | {data_node_2,data_node_3} | data_node_2 - hyper2 | _timescaledb_internal._dist_hyper_11_17_chunk | {data_node_1,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 -(12 rows) - --- test alter_data_node permissions -\set ON_ERROR_STOP 0 --- must be owner to alter a data node -SELECT * FROM alter_data_node('data_node_1', available=>false); -WARNING: altering data node is deprecated -ERROR: must be owner of foreign server data_node_1 -SELECT * FROM alter_data_node('data_node_1', port=>8989); -WARNING: altering data node is deprecated -ERROR: must be owner of foreign server data_node_1 -\set ON_ERROR_STOP 1 --- query some data from all hypertables to show its working before --- simulating the node being down -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - --- simulate a node being down by renaming the database for --- data_node_1, but for that to work we need to reconnect the backend --- to clear out the connection cache -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -ALTER DATABASE :DN_DBNAME_1 RENAME TO data_node_1_unavailable; -WARNING: you need to manually restart any running background workers after this command -\set ON_ERROR_STOP 0 -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -ERROR: could not connect to "data_node_1" -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; -ERROR: could not connect to "data_node_1" -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; -ERROR: could not connect to "data_node_1" -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; -ERROR: could not connect to "data_node_1" -\set ON_ERROR_STOP 1 --- alter the node as not available -SELECT * FROM alter_data_node('data_node_1', available=>false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 1 chunks - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_1 | localhost | 55432 | db_data_node_1 | f -(1 row) - --- the node that is not available for reads should no longer be --- query data node for chunks, except for those that have no --- alternative (i.e., the chunk only has one data node). -SELECT * FROM chunk_query_data_node; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper1 | _timescaledb_internal._dist_hyper_10_12_chunk | {data_node_1} | data_node_1 - hyper1 | _timescaledb_internal._dist_hyper_10_13_chunk | {data_node_2} | data_node_2 - hyper1 | _timescaledb_internal._dist_hyper_10_14_chunk | {data_node_3} | data_node_3 - hyper2 | _timescaledb_internal._dist_hyper_11_15_chunk | {data_node_1,data_node_2} | data_node_2 - hyper2 | _timescaledb_internal._dist_hyper_11_16_chunk | {data_node_2,data_node_3} | data_node_2 - hyper2 | _timescaledb_internal._dist_hyper_11_17_chunk | {data_node_1,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 -(12 rows) - --- queries should work again, except on hyper1 which has no --- replication -\set ON_ERROR_STOP 0 -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -ERROR: data node "data_node_1" is not available -\set ON_ERROR_STOP 1 -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - --- inserts should continue to work and should go to the "live" --- datanodes -INSERT INTO hyper3 VALUES ('2022-01-03 00:00:00', 1, 1); -INSERT INTO hyper3 VALUES ('2022-01-03 00:00:05', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-03 00:00:00', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-03 00:00:05', 1, 1); --- Check that the metadata on the AN removes the association with --- the "unavailable" DN for existing chunks that are being written into --- above -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 -(6 rows) - --- Also, inserts should work if going to a new chunk -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:00', 1, 1); -WARNING: insufficient number of data nodes -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:05', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:00', 1, 1); -WARNING: insufficient number of data nodes -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:05', 1, 1); --- Also check that new chunks only use the "available" DNs -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_24_chunk | {data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_25_chunk | {data_node_2,data_node_3} | data_node_2 -(8 rows) - --- Updates/Deletes should also work -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:00'; - time | location | temp -------------------------------+----------+------ - Mon Jan 03 00:00:00 2022 PST | 1 | 10 - Mon Jan 03 00:00:00 2022 PST | 2 | 10 -(2 rows) - -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:05'; - time | location | temp -------------------------------+----------+------ - Mon Jan 03 00:00:05 2022 PST | 1 | 10 -(1 row) - -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; - time | location | temp -------------------------------+----------+------ - Mon Jan 03 00:00:00 2022 PST | 2 | 10 - Mon Jan 03 00:00:00 2022 PST | 1 | 10 -(2 rows) - -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; - time | location | temp -------------------------------+----------+------ - Mon Jan 03 00:00:05 2022 PST | 1 | 10 -(1 row) - -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:00'; - time | location | temp -------+----------+------ -(0 rows) - -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:05'; - time | location | temp -------+----------+------ -(0 rows) - -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; - time | location | temp -------+----------+------ -(0 rows) - -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; - time | location | temp -------+----------+------ -(0 rows) - --- Inserts directly into chunks using FDW should also work and should go to the --- available DNs appropriately -INSERT INTO _timescaledb_internal._dist_hyper_12_24_chunk VALUES ('2022-01-11 00:00:00', 1, 1); -INSERT INTO _timescaledb_internal._dist_hyper_13_25_chunk VALUES ('2022-01-11 00:00:00', 1, 1); -SELECT * FROM test.remote_exec(ARRAY['data_node_2', 'data_node_3'], $$ SELECT * FROM _timescaledb_internal._dist_hyper_12_24_chunk WHERE time = '2022-01-11 00:00:00'; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_2]: SELECT * FROM _timescaledb_internal._dist_hyper_12_24_chunk WHERE time = '2022-01-11 00:00:00' -NOTICE: [data_node_2]: -time |location|temp -----------------------------+--------+---- -Tue Jan 11 00:00:00 2022 PST| 1| 1 -(1 row) - - -NOTICE: [data_node_3]: SELECT * FROM _timescaledb_internal._dist_hyper_12_24_chunk WHERE time = '2022-01-11 00:00:00' -NOTICE: [data_node_3]: -time |location|temp -----------------------------+--------+---- -Tue Jan 11 00:00:00 2022 PST| 1| 1 -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY['data_node_2', 'data_node_3'], $$ SELECT * FROM _timescaledb_internal._dist_hyper_13_25_chunk WHERE time = '2022-01-11 00:00:00'; $$); -WARNING: executing remote command is deprecated -NOTICE: [data_node_2]: SELECT * FROM _timescaledb_internal._dist_hyper_13_25_chunk WHERE time = '2022-01-11 00:00:00' -NOTICE: [data_node_2]: -time |location|temp -----------------------------+--------+---- -Tue Jan 11 00:00:00 2022 PST| 1| 1 -(1 row) - - -NOTICE: [data_node_3]: SELECT * FROM _timescaledb_internal._dist_hyper_13_25_chunk WHERE time = '2022-01-11 00:00:00' -NOTICE: [data_node_3]: -time |location|temp -----------------------------+--------+---- -Tue Jan 11 00:00:00 2022 PST| 1| 1 -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_24_chunk | {data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_25_chunk | {data_node_2,data_node_3} | data_node_2 -(8 rows) - -SELECT hypertable_name, chunk_name, data_nodes FROM timescaledb_information.chunks -WHERE hypertable_name IN ('hyper3', 'hyper_1dim') -AND range_start::timestamptz <= '2022-01-10 00:00:00' -AND range_end::timestamptz > '2022-01-10 00:00:00' -ORDER BY 1, 2; - hypertable_name | chunk_name | data_nodes ------------------+-------------------------+--------------------------- - hyper3 | _dist_hyper_12_24_chunk | {data_node_2,data_node_3} - hyper_1dim | _dist_hyper_13_25_chunk | {data_node_2,data_node_3} -(2 rows) - --- DDL should error out even if one DN is unavailable -\set ON_ERROR_STOP 0 -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ERROR: some data nodes are not available for DDL commands -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; -ERROR: some data nodes are not available for DDL commands -\set ON_ERROR_STOP 1 --- Mark all DNs unavailable. Metadata should still retain last DN but all --- activity should fail -SELECT * FROM alter_data_node('data_node_2', available=>false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 2 chunks - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_2 | localhost | 55432 | db_data_node_2 | f -(1 row) - -SELECT * FROM alter_data_node('data_node_3', available=>false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 11 chunks - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_3 | localhost | 55432 | db_data_node_3 | f -(1 row) - -\set ON_ERROR_STOP 0 -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:00', 1, 1); -ERROR: insufficient number of available data nodes -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:00', 1, 1); -ERROR: insufficient number of available data nodes -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -ERROR: insufficient number of available data nodes -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -ERROR: insufficient number of available data nodes -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -ERROR: insufficient number of available data nodes -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -ERROR: insufficient number of available data nodes -SELECT count(*) FROM hyper3; -ERROR: data node "data_node_3" is not available -SELECT count(*) FROM hyper_1dim; -ERROR: data node "data_node_3" is not available -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ERROR: some data nodes are not available for DDL commands -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; -ERROR: some data nodes are not available for DDL commands -\set ON_ERROR_STOP 1 --- re-enable the data node and the chunks should "switch back" to --- using the data node. However, only the chunks for which the node is --- "primary" should switch to using the data node for queries -ALTER DATABASE data_node_1_unavailable RENAME TO :DN_DBNAME_1; -WARNING: you need to manually restart any running background workers after this command -SELECT * FROM alter_data_node('data_node_1', available=>true); -WARNING: altering data node is deprecated -WARNING: insufficient number of data nodes -WARNING: insufficient number of data nodes - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_1 | localhost | 55432 | db_data_node_1 | t -(1 row) - -SELECT * FROM alter_data_node('data_node_2', available=>true); -WARNING: altering data node is deprecated -WARNING: insufficient number of data nodes -WARNING: insufficient number of data nodes -WARNING: insufficient number of data nodes -WARNING: insufficient number of data nodes - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_2 | localhost | 55432 | db_data_node_2 | t -(1 row) - -SELECT * FROM alter_data_node('data_node_3', available=>true); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_3 | localhost | 55432 | db_data_node_3 | t -(1 row) - -SELECT * FROM chunk_query_data_node; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - hyper1 | _timescaledb_internal._dist_hyper_10_12_chunk | {data_node_1} | data_node_1 - hyper1 | _timescaledb_internal._dist_hyper_10_13_chunk | {data_node_2} | data_node_2 - hyper1 | _timescaledb_internal._dist_hyper_10_14_chunk | {data_node_3} | data_node_3 - hyper2 | _timescaledb_internal._dist_hyper_11_15_chunk | {data_node_1,data_node_2} | data_node_1 - hyper2 | _timescaledb_internal._dist_hyper_11_16_chunk | {data_node_2,data_node_3} | data_node_2 - hyper2 | _timescaledb_internal._dist_hyper_11_17_chunk | {data_node_1,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_18_chunk | {data_node_2,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_19_chunk | {data_node_2,data_node_3} | data_node_2 - hyper3 | _timescaledb_internal._dist_hyper_12_20_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - hyper3 | _timescaledb_internal._dist_hyper_12_24_chunk | {data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_21_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_22_chunk | {data_node_2,data_node_3} | data_node_3 - hyper_1dim | _timescaledb_internal._dist_hyper_13_23_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - hyper_1dim | _timescaledb_internal._dist_hyper_13_25_chunk | {data_node_2,data_node_3} | data_node_3 -(14 rows) - ---queries should work again on all tables -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - time | location -------------------------------+---------- - Sat Jan 01 00:00:00 2022 PST | 1 -(1 row) - --- DDL should also work again -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; --- save old port so that we can restore connectivity after we test --- changing the connection information for the data node -WITH options AS ( - SELECT unnest(options) opt - FROM timescaledb_information.data_nodes - WHERE node_name = 'data_node_1' -) -SELECT split_part(opt, '=', 2) AS old_port -FROM options WHERE opt LIKE 'port%' \gset --- also test altering host, port and database -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; - node_name | options --------------+------------------------------------------------------------------ - data_node_1 | {host=localhost,port=55432,dbname=db_data_node_1,available=true} - data_node_2 | {host=localhost,port=55432,dbname=db_data_node_2,available=true} - data_node_3 | {host=localhost,port=55432,dbname=db_data_node_3,available=true} -(3 rows) - -SELECT * FROM alter_data_node('data_node_1', available=>true, host=>'foo.bar', port=>8989, database=>'new_db'); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+---------+------+----------+----------- - data_node_1 | foo.bar | 8989 | new_db | t -(1 row) - -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; - node_name | options --------------+------------------------------------------------------------------ - data_node_1 | {host=foo.bar,port=8989,dbname=new_db,available=true} - data_node_2 | {host=localhost,port=55432,dbname=db_data_node_2,available=true} - data_node_3 | {host=localhost,port=55432,dbname=db_data_node_3,available=true} -(3 rows) - --- just show current options: -SELECT * FROM alter_data_node('data_node_1'); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+---------+------+----------+----------- - data_node_1 | foo.bar | 8989 | new_db | t -(1 row) - -DROP TABLE hyper1; -DROP TABLE hyper2; -DROP TABLE hyper3; -DROP TABLE hyper_1dim; -\set ON_ERROR_STOP 0 --- test some error cases -SELECT * FROM alter_data_node(NULL); -WARNING: altering data node is deprecated -ERROR: data node name cannot be NULL -SELECT * FROM alter_data_node('does_not_exist'); -WARNING: altering data node is deprecated -ERROR: server "does_not_exist" does not exist -SELECT * FROM alter_data_node('data_node_1', port=>89000); -WARNING: altering data node is deprecated -ERROR: invalid port number 89000 --- cannot delete data node with "drop_database" since configuration is wrong -SELECT delete_data_node('data_node_1', drop_database=>true); -WARNING: deleting data node is deprecated -ERROR: could not connect to data node "data_node_1" -\set ON_ERROR_STOP 1 --- restore configuration for data_node_1 -SELECT * FROM alter_data_node('data_node_1', host=>'localhost', port=>:old_port, database=>:'DN_DBNAME_1'); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+----------------+----------- - data_node_1 | localhost | 55432 | db_data_node_1 | t -(1 row) - -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; - node_name | options --------------+------------------------------------------------------------------ - data_node_1 | {host=localhost,port=55432,dbname=db_data_node_1,available=true} - data_node_2 | {host=localhost,port=55432,dbname=db_data_node_2,available=true} - data_node_3 | {host=localhost,port=55432,dbname=db_data_node_3,available=true} -(3 rows) - -DROP VIEW chunk_query_data_node; --- create new session to clear out connection cache -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT delete_data_node('data_node_1', drop_database=>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT delete_data_node('data_node_2', drop_database=>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT delete_data_node('data_node_3', drop_database=>true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - diff --git a/tsl/test/expected/data_node_bootstrap.out b/tsl/test/expected/data_node_bootstrap.out deleted file mode 100644 index d03bdb91214..00000000000 --- a/tsl/test/expected/data_node_bootstrap.out +++ /dev/null @@ -1,708 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER; -CREATE OR REPLACE FUNCTION show_data_nodes() -RETURNS TABLE(data_node_name NAME, host TEXT, dbname NAME) -AS :TSL_MODULE_PATHNAME, 'ts_test_data_node_show' LANGUAGE C; --- Fetch the encoding, collation, and ctype as quoted strings into --- variables. -SELECT QUOTE_LITERAL(PG_ENCODING_TO_CHAR(encoding)) AS enc - , QUOTE_LITERAL(datcollate) AS coll - , QUOTE_LITERAL(datctype) AS ctype - FROM pg_database - WHERE datname = current_database() - \gset -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | t | t -(1 row) - --- Ensure database and extensions are installed and have the correct --- encoding, ctype and collation. -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SELECT extname, extnamespace::regnamespace FROM pg_extension e WHERE extname = 'timescaledb'; - extname | extnamespace --------------+-------------- - timescaledb | public -(1 row) - -SELECT PG_ENCODING_TO_CHAR(encoding) = :enc - , datcollate = :coll - , datctype = :ctype - FROM pg_database - WHERE datname = current_database(); - ?column? | ?column? | ?column? -----------+----------+---------- - t | t | t -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- After delete_data_node, the database and extension should still --- exist on the data node -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM show_data_nodes(); - data_node_name | host | dbname -----------------+------+-------- -(0 rows) - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SELECT extname, extnamespace::regnamespace FROM pg_extension e WHERE extname = 'timescaledb'; - extname | extnamespace --------------+-------------- - timescaledb | public -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 --- Trying to add the data node again should fail, with or without --- bootstrapping. -SELECT add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap=>false); -WARNING: adding data node is deprecated -ERROR: cannot add "bootstrap_test" as a data node -SELECT add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); -WARNING: adding data node is deprecated -NOTICE: database "bootstrap_test" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "bootstrap_test" as a data node -\set ON_ERROR_STOP 0 -DROP DATABASE bootstrap_test WITH (FORCE); ----------------------------------------------------------------------- --- Bootstrap the database and check that calling it without --- bootstrapping does not find any problems. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | t | t -(1 row) - -SELECT * FROM show_data_nodes(); - data_node_name | host | dbname -----------------+-----------+---------------- - bootstrap_test | localhost | bootstrap_test -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; --- This should show dist_uuid row on the deleted node since that is --- not removed by delete_data_node. -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - key ------------ - dist_uuid -(1 row) - --- Delete the dist_uuid so that we can try to re-add it without --- bootstrapping. -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | f | f -(1 row) - -\set ON_ERROR_STOP 0 --- Dropping the database with delete_data_node should not work in a --- transaction block since it is non-transactional. -BEGIN; -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -WARNING: deleting data node is deprecated -ERROR: delete_data_node() cannot run inside a transaction block -ROLLBACK; -\set ON_ERROR_STOP 1 -CREATE TABLE conditions (time timestamptz, device int, temp float); -SELECT create_distributed_hypertable('conditions', 'time', 'device'); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (1,public,conditions,t) -(1 row) - -\set ON_ERROR_STOP 0 --- Should fail because the data node is the last one -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -WARNING: deleting data node is deprecated -ERROR: insufficient number of data nodes for distributed hypertable "conditions" -\set ON_ERROR_STOP 1 --- Add another data node -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test_2', host => 'localhost', database => 'bootstrap_test_2', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------+------------------+--------------+------------------+------------------- - bootstrap_test_2 | bootstrap_test_2 | t | t | t -(1 row) - -SELECT attach_data_node('bootstrap_test_2', 'conditions'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "device" was increased to 2 - attach_data_node ------------------------- - (1,1,bootstrap_test_2) -(1 row) - --- Insert some data into the node -INSERT INTO conditions VALUES ('2021-12-01 10:30', 2, 20.3); -\set ON_ERROR_STOP 0 --- Should fail because the data node still holds data -SELECT * FROM delete_data_node('bootstrap_test_2', drop_database => true); -WARNING: deleting data node is deprecated -ERROR: insufficient number of data nodes -\set ON_ERROR_STOP 1 --- Data node's database still exists after failure to delete -SELECT count(*) FROM pg_database WHERE datname = 'bootstrap_test_2'; - count -------- - 1 -(1 row) - --- Delete the chunks so that we can delete the data node -SELECT drop_chunks('conditions', older_than => '2022-01-01'::timestamptz); - drop_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test_2', drop_database => true); -WARNING: deleting data node is deprecated -NOTICE: the number of partitions in dimension "device" of hypertable "conditions" was decreased to 1 - delete_data_node ------------------- - t -(1 row) - --- The data node's database is dropped -SELECT count(*) FROM pg_database WHERE datname = 'bootstrap_test_2'; - count -------- - 0 -(1 row) - -SELECT data_nodes FROM timescaledb_information.hypertables -WHERE hypertable_name = 'conditions'; - data_nodes ------------------- - {bootstrap_test} -(1 row) - --- Using the drop_database option when there are active connections to --- the data node should fail. But any connections in the current --- session should be cleared when dropping the database. To test that --- the connection is cleared, first create a connection in the --- connection cache by inserting some data -INSERT INTO conditions VALUES ('2021-12-01 10:30', 1, 20.3); -DROP TABLE conditions; --- Now drop the data node and it should clear the connection from the --- cache first -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -\set ON_ERROR_STOP 0 --- Dropping the database now should fail since it no longer exists -DROP DATABASE bootstrap_test WITH (FORCE); -ERROR: database "bootstrap_test" does not exist -\set ON_ERROR_STOP 1 --- Adding the data node again should work -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | t | t -(1 row) - --- Now drop the database manually before using the drop_database option -DROP DATABASE bootstrap_test WITH (FORCE); -\set ON_ERROR_STOP 0 --- Expect an error since the database does not exist. -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -WARNING: deleting data node is deprecated -ERROR: [bootstrap_test]: database "bootstrap_test" does not exist -\set ON_ERROR_STOP 1 --- Delete it without the drop_database option set since the database --- was manually deleted. -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - ----------------------------------------------------------------------- --- Do a manual bootstrap of the data node and check that it can be --- added. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | f | f -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -DROP DATABASE bootstrap_test WITH (FORCE); ----------------------------------------------------------------------- --- Do a manual bootstrap of the data node and check that it can be --- added even when bootstrap is true. This is to check that we can --- bootstrap a database with an extension already installed. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "bootstrap_test" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | f | f -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -DROP DATABASE bootstrap_test WITH (FORCE); ----------------------------------------------------------------------- --- Create a database and check that a mismatching encoding is caught --- when bootstrapping (since it will skip creating the database). -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE bootstrap_test - ENCODING SQL_ASCII - LC_COLLATE 'C' - LC_CTYPE 'C' - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated -ERROR: database exists but has wrong encoding -\set ON_ERROR_STOP 1 -DROP DATABASE bootstrap_test WITH (FORCE); ----------------------------------------------------------------------- --- Do a manual bootstrap of the data but check that a mismatching --- encoding, ctype, or collation will be caught. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Pick an alternative locale for testing from the list of installed --- collations. This locale needs to be differnt from the current --- database's locale. We pick it from the list of collations in a --- platform agnostic way since, e.g., Linux and Windows have very --- different locale names. -SELECT QUOTE_LITERAL(c.collctype) AS other_locale - FROM pg_collation c, pg_database d - WHERE c.collencoding = d.encoding - AND d.datctype != c.collctype - AND d.datname = current_database() - ORDER BY c.oid DESC - LIMIT 1 - \gset -CREATE DATABASE bootstrap_test - ENCODING SQL_ASCII - LC_COLLATE 'C' - LC_CTYPE 'C' - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: database exists but has wrong encoding -\set ON_ERROR_STOP 1 -DROP DATABASE bootstrap_test WITH (FORCE); -CREATE DATABASE bootstrap_test - ENCODING :"enc" - LC_COLLATE :other_locale - LC_CTYPE :ctype - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: database exists but has wrong collation -\set ON_ERROR_STOP 1 -DROP DATABASE bootstrap_test WITH (FORCE); -CREATE DATABASE bootstrap_test - ENCODING :"enc" - LC_COLLATE :coll - LC_CTYPE :other_locale - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: database exists but has wrong LC_CTYPE -\set ON_ERROR_STOP 1 -DROP DATABASE bootstrap_test WITH (FORCE); ------------------------------------------------------------------------ --- Bootstrap the database and remove it. Check that the missing --- database is caught when adding the node and not bootstrapping. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | t | t -(1 row) - -SELECT * FROM show_data_nodes(); - data_node_name | host | dbname -----------------+-----------+---------------- - bootstrap_test | localhost | bootstrap_test -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -DROP DATABASE bootstrap_test WITH (FORCE); -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: could not connect to "bootstrap_test" -\set ON_ERROR_STOP 1 ------------------------------------------------------------------------ --- Bootstrap the database and remove the extension. --- --- Check that adding the data node and not bootstrapping will fail --- indicating that the extension is missing. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - bootstrap_test | bootstrap_test | t | t | t -(1 row) - -SELECT * FROM delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -\c bootstrap_test :ROLE_SUPERUSER; -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; - extname -------------- - timescaledb -(1 row) - -DROP EXTENSION timescaledb CASCADE; -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; - extname ---------- -(0 rows) - -\set ON_ERROR_STOP 0 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "bootstrap_test" as a data node -\set ON_ERROR_STOP 1 -DROP DATABASE bootstrap_test WITH (FORCE); ------------------------------------------------------------------------ --- Create a new access node manually so that we can set a specific --- schema for the access node and then bootstrap a data node partially --- with a non-public schema so that we can see that an error is --- generated. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE DATABASE access_node OWNER :ROLE_CLUSTER_SUPERUSER; -\c access_node :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER; -CREATE EXTENSION timescaledb WITH SCHEMA ts_non_default CASCADE; -SET client_min_messages TO NOTICE; --- Show the schema for the extension to verify that it is not public. -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; - extname -------------- - timescaledb -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO NOTICE; -\c access_node :ROLE_CLUSTER_SUPERUSER --- Add data node and delete it under error suppression. We want to --- avoid later tests to have random failures because the add succeeds. -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM ts_non_default.add_data_node( - 'bootstrap_test', host => 'localhost', - database => 'bootstrap_test', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "bootstrap_test" already exists on data node, skipping -ERROR: schema "ts_non_default" already exists in database, aborting -SELECT * FROM ts_non_default.delete_data_node('bootstrap_test'); -WARNING: deleting data node is deprecated -ERROR: server "bootstrap_test" does not exist -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE bootstrap_test WITH (FORCE); -DROP DATABASE access_node WITH (FORCE); ----------------------------------------------------------------------- --- Test for ongoing transaction -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -BEGIN; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); -WARNING: adding data node is deprecated -ERROR: add_data_node() cannot run inside a transaction block -\set ON_ERROR_STOP 1 -COMMIT; -SELECT * FROM show_data_nodes(); - data_node_name | host | dbname -----------------+------+-------- -(0 rows) - ---------------------------------------------------------------------- --- Test unusual database names --- --- bootstrap_database = 'postgres' -CREATE FUNCTION test_database_name(name TEXT) RETURNS void AS $$ -BEGIN - PERFORM add_data_node('_test1', host => 'localhost', database => name); - PERFORM delete_data_node('_test1'); -END; -$$ LANGUAGE plpgsql; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT test_database_name('Unusual Name'); -WARNING: adding data node is deprecated -WARNING: deleting data node is deprecated - test_database_name --------------------- - -(1 row) - -SELECT test_database_name(U&'\0441\043B\043E\043D'); -WARNING: adding data node is deprecated -WARNING: deleting data node is deprecated - test_database_name --------------------- - -(1 row) - -DROP DATABASE "Unusual Name" WITH (FORCE); -DROP DATABASE U&"\0441\043B\043E\043D" WITH (FORCE); --- Test Access Node DATABASE DROP NOTICE message --- --- Make sure the NOTICE message not shown on a DROP DATABASE error -\set ON_ERROR_STOP 0 -DROP DATABASE :TEST_DBNAME WITH (FORCE); -ERROR: cannot drop the currently open database -\set ON_ERROR_STOP 1 -CREATE DATABASE drop_db_test; -\c drop_db_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; --- No security label exists -SELECT label FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; - label -------- -(0 rows) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('drop_db_test_dn', host => 'localhost', database => 'drop_db_test_dn'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - drop_db_test_dn | drop_db_test_dn | t | t | t -(1 row) - --- Make sure security label is created -SELECT substr(label, 0, 10) || ':uuid' - FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; - ?column? ----------------- - dist_uuid:uuid -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Check that timescaledb security label cannot be used directly. To --- support pg_dump, we do not print an error when a proper label is --- used, but print an error if something that doesn't look like a --- distributed uuid is used. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11ec-8919-23804e22321a'; -\set ON_ERROR_STOP 0 -\set VERBOSITY default --- No colon -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'bad_label'; -ERROR: TimescaleDB label is for internal use only -DETAIL: Security label is "bad_label". -HINT: Security label has to be of format "dist_uuid:". --- Bad tag, but still an UUID -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'uuid:4ab3b1bc-438f-11ec-8919-23804e22321a'; -ERROR: TimescaleDB label is for internal use only -DETAIL: Security label is "uuid:4ab3b1bc-438f-11ec-8919-23804e22321a". -HINT: Security label has to be of format "dist_uuid:". --- Length is not correct -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e2232'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bcd-438f-11ec-8919-23804e2232" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e223215'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bcd-438f-11ec-8919-23804e223215" -HINT: Security label has to be of format "dist_uuid:". --- Length is correct, but it contains something that is not a --- hexadecimal digit. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-4x8f-11ec-8919-23804e22321'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bcd-4x8f-11ec-8919-23804e22321" -HINT: Security label has to be of format "dist_uuid:". --- Total length is correct, but not the right number of hyphens. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3-1bcd-438f-11ec-8919-23804e22321'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3-1bcd-438f-11ec-8919-23804e22321" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd438f-11ec-8919-23804e223213'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bcd438f-11ec-8919-23804e223213" -HINT: Security label has to be of format "dist_uuid:". --- Total length is correct, but length of groups is not -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e22321'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bcd-438f-11ec-8919-23804e22321" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11ec-891-23804e22321ab'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bc-438f-11ec-891-23804e22321ab" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11e-8919-23804e22321ab'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bc-438f-11e-8919-23804e22321ab" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438-11ec-8919-23804e22321ab'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bc-438-11ec-8919-23804e22321ab" -HINT: Security label has to be of format "dist_uuid:". -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bca-438f-11ec-8919-23804e22321'; -ERROR: TimescaleDB label is for internal use only -DETAIL: invalid input syntax for type uuid: "4ab3b1bca-438f-11ec-8919-23804e22321" -HINT: Security label has to be of format "dist_uuid:". -\set VERBOSITY terse -\set ON_ERROR_STOP 1 --- Check that security label functionality is working -CREATE TABLE seclabel_test(id int); -SECURITY LABEL ON TABLE seclabel_test IS 'label'; -DROP TABLE seclabel_test; --- This will generate NOTICE message -DROP DATABASE drop_db_test WITH (FORCE); -NOTICE: TimescaleDB distributed database might require additional cleanup on the data nodes -DROP DATABASE drop_db_test_dn WITH (FORCE); --- Ensure label is deleted after the DROP -SELECT label FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; - label -------- -(0 rows) - diff --git a/tsl/test/expected/debug_notice.out b/tsl/test/expected/debug_notice.out deleted file mode 100644 index b40269bb4ba..00000000000 --- a/tsl/test/expected/debug_notice.out +++ /dev/null @@ -1,277 +0,0 @@ --- 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. --- This test suite is not intended to check the output of the queries --- but rather make sure that they are generated when certain flags are --- enabled or disabled. --- --- The queries below are triggering a call to `tsl_set_rel_pathlist` --- and `get_foreign_upper_paths` respectively, but if that changes, --- they might need to be changed. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------------+-------------------+--------------+------------------+------------------- - db_debug_notice_1 | db_debug_notice_1 | t | t | t - db_debug_notice_2 | db_debug_notice_2 | t | t | t - db_debug_notice_3 | db_debug_notice_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -CREATE TABLE hyper (time timestamptz, device int, location int, temp float); -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | hyper | t -(1 row) - -SET enable_partitionwise_aggregate = ON; -INSERT INTO hyper VALUES - ('2018-01-19 13:01', 1, 2, 2.3), - ('2018-01-20 15:05', 1, 3, 5.3), - ('2018-02-21 13:01', 3, 4, 1.5), - ('2018-02-28 15:05', 1, 1, 5.6), - ('2018-02-19 13:02', 3, 5, 3.1), - ('2018-02-19 13:02', 2, 3, 6.7), - ('2018-03-08 11:05', 6, 2, 8.1), - ('2018-03-08 11:05', 7, 4, 4.6), - ('2018-03-10 17:02', 5, 5, 5.1), - ('2018-03-10 17:02', 1, 6, 9.1), - ('2018-03-17 12:02', 2, 2, 6.7), - ('2018-04-19 13:01', 1, 2, 7.6), - ('2018-04-20 15:08', 5, 5, 6.4), - ('2018-05-19 13:01', 4, 4, 5.1), - ('2018-05-20 15:08', 5, 1, 9.4), - ('2018-05-30 13:02', 3, 2, 9.0); --- Update table stats -ANALYZE hyper; --- Optimizer debug messages shown at debug level 2 -SET client_min_messages TO DEBUG2; --- Turning on show_rel should show a message --- But disable the code which avoids dist chunk planning -SET timescaledb.debug_allow_datanode_only_path = 'off'; -LOG: statement: SET timescaledb.debug_allow_datanode_only_path = 'off'; -SET timescaledb.debug_optimizer_flags = 'show_rel'; -LOG: statement: SET timescaledb.debug_optimizer_flags = 'show_rel'; -SHOW timescaledb.debug_optimizer_flags; -LOG: statement: SHOW timescaledb.debug_optimizer_flags; - timescaledb.debug_optimizer_flags ------------------------------------ - show_rel -(1 row) - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -LOG: statement: SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -DEBUG: creating per chunk append paths -DEBUG: RELOPTINFO [rel name: _timescaledb_internal._dist_hyper_1_8_chunk hyper, type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=1 width=20 -Path list: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 - - -DEBUG: RELOPTINFO [rel name: _timescaledb_internal._dist_hyper_1_9_chunk hyper, type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=1 width=20 -Path list: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 - - -DEBUG: RELOPTINFO [rel name: _timescaledb_internal._dist_hyper_1_10_chunk hyper, type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=2 width=20 -Path list: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=2 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=2 - - -DEBUG: RELOPTINFO [rel name: _timescaledb_internal._dist_hyper_1_11_chunk hyper, type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=1 width=20 -Path list: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - ForeignPath [rel type: FOREIGN_TABLE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 - - -DEBUG: RELOPTINFO [rel name: public.hyper, type: DATA_NODE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=1 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 - -Cheapest parameterized paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest startup path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest total path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - -DEBUG: RELOPTINFO [rel name: public.hyper, type: DATA_NODE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=3 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 - -Cheapest parameterized paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest startup path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest total path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - -DEBUG: RELOPTINFO [rel name: public.hyper, type: DATA_NODE, kind: OTHER_MEMBER_REL, base rel names: hyper] rows=1 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 - -Cheapest parameterized paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest startup path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - -Cheapest total path: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - -DEBUG: RELOPTINFO [rel name: public.hyper, type: HYPERTABLE, kind: BASEREL, base rel names: hyper] rows=5 width=20 -Path list: - AppendPath [rel type: HYPERTABLE, kind: BASEREL, parent's base rels: hyper] rows=5 - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - MergeAppendPath [rel type: HYPERTABLE, kind: BASEREL, parent's base rels: hyper] rows=5 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=3 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_MEMBER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - - time | device | temp -------------------------------+--------+------ - Thu Apr 19 13:01:00 2018 PDT | 1 | 7.6 - Fri Apr 20 15:08:00 2018 PDT | 5 | 6.4 - Sat May 19 13:01:00 2018 PDT | 4 | 5.1 - Sun May 20 15:08:00 2018 PDT | 5 | 9.4 - Wed May 30 13:02:00 2018 PDT | 3 | 9 -(5 rows) - --- Enable session level datanode only path parameter which doesn't --- plan distributed chunk scans unnecessarily -SET timescaledb.debug_allow_datanode_only_path = 'on'; -LOG: statement: SET timescaledb.debug_allow_datanode_only_path = 'on'; --- Turning off the show_rel (and turning on another flag) should not --- show a notice on the relations, but show the upper paths. -SET timescaledb.debug_optimizer_flags = 'show_upper=*'; -LOG: statement: SET timescaledb.debug_optimizer_flags = 'show_upper=*'; -SHOW timescaledb.debug_optimizer_flags; -LOG: statement: SHOW timescaledb.debug_optimizer_flags; - timescaledb.debug_optimizer_flags ------------------------------------ - show_upper=* -(1 row) - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -LOG: statement: SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -DEBUG: avoiding per chunk append paths -DEBUG: Upper rel stage GROUP_AGG: -RELOPTINFO [rel name: Aggregate on (public.hyper), type: DATA_NODE, kind: OTHER_UPPER_REL, base rel names: hyper] rows=0 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - -DEBUG: Upper rel stage GROUP_AGG: -RELOPTINFO [rel name: Aggregate on (public.hyper), type: DATA_NODE, kind: OTHER_UPPER_REL, base rel names: hyper] rows=0 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 - - -DEBUG: Upper rel stage GROUP_AGG: -RELOPTINFO [rel name: Aggregate on (public.hyper), type: DATA_NODE, kind: OTHER_UPPER_REL, base rel names: hyper] rows=0 width=20 -Path list: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) -Pruned paths: - CustomPath (DataNodeScanPath) [rel type: DATA_NODE, kind: OTHER_UPPER_REL, parent's base rels: hyper] rows=1 with pathkeys: ((hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time, hyper.time), (hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device, hyper.device)) - - - time | device | temp -------------------------------+--------+------ - Thu Apr 19 13:01:00 2018 PDT | 1 | 7.6 - Fri Apr 20 15:08:00 2018 PDT | 5 | 6.4 - Sat May 19 13:01:00 2018 PDT | 4 | 5.1 - Sun May 20 15:08:00 2018 PDT | 5 | 9.4 - Wed May 30 13:02:00 2018 PDT | 3 | 9 -(5 rows) - --- Turning off both relations should not show anything. -RESET timescaledb.debug_optimizer_flags; -LOG: statement: RESET timescaledb.debug_optimizer_flags; -SHOW timescaledb.debug_optimizer_flags; -LOG: statement: SHOW timescaledb.debug_optimizer_flags; - timescaledb.debug_optimizer_flags ------------------------------------ - -(1 row) - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -LOG: statement: SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; -DEBUG: avoiding per chunk append paths - time | device | temp -------------------------------+--------+------ - Thu Apr 19 13:01:00 2018 PDT | 1 | 7.6 - Fri Apr 20 15:08:00 2018 PDT | 5 | 6.4 - Sat May 19 13:01:00 2018 PDT | 4 | 5.1 - Sun May 20 15:08:00 2018 PDT | 5 | 9.4 - Wed May 30 13:02:00 2018 PDT | 3 | 9 -(5 rows) - -SET client_min_messages TO ERROR; -LOG: statement: SET client_min_messages TO ERROR; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_api_calls.out b/tsl/test/expected/dist_api_calls.out deleted file mode 100644 index c779874724c..00000000000 --- a/tsl/test/expected/dist_api_calls.out +++ /dev/null @@ -1,398 +0,0 @@ --- 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. --- Basic testing of API functions on distributed hypertable --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ----------------------+---------------------+--------------+------------------+------------------- - db_dist_api_calls_1 | db_dist_api_calls_1 | t | t | t - db_dist_api_calls_2 | db_dist_api_calls_2 | t | t | t - db_dist_api_calls_3 | db_dist_api_calls_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Create a distributed hypertable with data -SET ROLE :ROLE_1; -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -SELECT * FROM disttable ORDER BY time; - time | device | value -------------------------------+--------+---------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - Sun Jul 01 08:01:00 2018 PDT | 29 | 64 - Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - Mon Jul 02 08:01:00 2018 PDT | 87 | 0 -(8 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_api_calls_1]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_api_calls_2]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_5_chunk -(2 rows) - - -NOTICE: [db_dist_api_calls_3]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_6_chunk -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Test APIs on the distributed hypertable --- Call drop_chunks -SELECT drop_chunks('disttable', timestamptz '2017-03-01 00:00'); - drop_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - -SELECT * FROM disttable ORDER BY time; - time | device | value -------------------------------+--------+---------- - Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - Sun Jul 01 08:01:00 2018 PDT | 29 | 64 - Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - Mon Jul 02 08:01:00 2018 PDT | 87 | 0 -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_api_calls_1]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_4_chunk -(1 row) - - -NOTICE: [db_dist_api_calls_2]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_5_chunk -(1 row) - - -NOTICE: [db_dist_api_calls_3]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_6_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - --- Restore the state -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23); -SELECT * FROM disttable ORDER BY time; - time | device | value -------------------------------+--------+---------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - Sun Jul 01 08:01:00 2018 PDT | 29 | 64 - Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - Mon Jul 02 08:01:00 2018 PDT | 87 | 0 -(8 rows) - -SELECT * FROM show_chunks('disttable'); - show_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk - _timescaledb_internal._dist_hyper_1_6_chunk - _timescaledb_internal._dist_hyper_1_7_chunk - _timescaledb_internal._dist_hyper_1_8_chunk - _timescaledb_internal._dist_hyper_1_9_chunk -(6 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_api_calls_1]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_4_chunk -_timescaledb_internal._dist_hyper_1_7_chunk -(2 rows) - - -NOTICE: [db_dist_api_calls_2]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_5_chunk -_timescaledb_internal._dist_hyper_1_9_chunk -(2 rows) - - -NOTICE: [db_dist_api_calls_3]: SELECT show_chunks('disttable') -NOTICE: [db_dist_api_calls_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_6_chunk -_timescaledb_internal._dist_hyper_1_8_chunk -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure that move_chunk() and reorder_chunk() functions cannot be used --- with distributed hypertable -SET ROLE TO DEFAULT; -SET client_min_messages TO error; -DROP TABLESPACE IF EXISTS tablespace1; -RESET client_min_messages; -CREATE TABLESPACE tablespace1 OWNER :ROLE_CLUSTER_SUPERUSER LOCATION :TEST_TABLESPACE1_PATH; -\set ON_ERROR_STOP 0 -SELECT move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_4_chunk', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'disttable_time_idx', verbose=>TRUE); -ERROR: move_chunk() and reorder_chunk() cannot be used with distributed hypertables -SELECT reorder_chunk('_timescaledb_internal._dist_hyper_1_4_chunk', verbose => TRUE); -ERROR: move_chunk() and reorder_chunk() cannot be used with distributed hypertables -\set ON_ERROR_STOP 1 -DROP TABLESPACE tablespace1; --- Ensure approximate_row_count() works with distributed hypertable --- -SELECT * FROM disttable ORDER BY time; - time | device | value -------------------------------+--------+---------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - Sun Jul 01 08:01:00 2018 PDT | 29 | 64 - Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - Mon Jul 02 08:01:00 2018 PDT | 87 | 0 -(8 rows) - -ANALYZE disttable; -SELECT count(*) FROM disttable; - count -------- - 8 -(1 row) - -SELECT approximate_row_count('disttable'); - approximate_row_count ------------------------ - 8 -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT approximate_row_count('disttable'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_api_calls_1]: SELECT approximate_row_count('disttable') -NOTICE: [db_dist_api_calls_1]: -approximate_row_count ---------------------- - 3 -(1 row) - - -NOTICE: [db_dist_api_calls_2]: SELECT approximate_row_count('disttable') -NOTICE: [db_dist_api_calls_2]: -approximate_row_count ---------------------- - 2 -(1 row) - - -NOTICE: [db_dist_api_calls_3]: SELECT approximate_row_count('disttable') -NOTICE: [db_dist_api_calls_3]: -approximate_row_count ---------------------- - 3 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test with native replication --- -CREATE TABLE disttable_repl( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable_repl', 'time', 'device', 3, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 2 | public | disttable_repl | t -(1 row) - -INSERT INTO disttable_repl VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -SELECT * FROM disttable_repl ORDER BY time; - time | device | value -------------------------------+--------+---------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - Sun Jul 01 08:01:00 2018 PDT | 29 | 64 - Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - Mon Jul 02 08:01:00 2018 PDT | 87 | 0 -(8 rows) - -SELECT * FROM show_chunks('disttable_repl'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_2_10_chunk - _timescaledb_internal._dist_hyper_2_11_chunk - _timescaledb_internal._dist_hyper_2_12_chunk - _timescaledb_internal._dist_hyper_2_13_chunk - _timescaledb_internal._dist_hyper_2_14_chunk - _timescaledb_internal._dist_hyper_2_15_chunk -(6 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable_repl'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_api_calls_1]: SELECT show_chunks('disttable_repl') -NOTICE: [db_dist_api_calls_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_2_10_chunk -_timescaledb_internal._dist_hyper_2_11_chunk -_timescaledb_internal._dist_hyper_2_13_chunk -_timescaledb_internal._dist_hyper_2_15_chunk -(4 rows) - - -NOTICE: [db_dist_api_calls_2]: SELECT show_chunks('disttable_repl') -NOTICE: [db_dist_api_calls_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_2_10_chunk -_timescaledb_internal._dist_hyper_2_12_chunk -_timescaledb_internal._dist_hyper_2_13_chunk -_timescaledb_internal._dist_hyper_2_14_chunk -(4 rows) - - -NOTICE: [db_dist_api_calls_3]: SELECT show_chunks('disttable_repl') -NOTICE: [db_dist_api_calls_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_2_11_chunk -_timescaledb_internal._dist_hyper_2_12_chunk -_timescaledb_internal._dist_hyper_2_14_chunk -_timescaledb_internal._dist_hyper_2_15_chunk -(4 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM disttable_repl; - count -------- - 8 -(1 row) - -SELECT approximate_row_count('disttable_repl'); - approximate_row_count ------------------------ - 0 -(1 row) - -ANALYZE disttable_repl; -SELECT approximate_row_count('disttable_repl'); - approximate_row_count ------------------------ - 8 -(1 row) - -DROP TABLE disttable_repl; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_backup.out b/tsl/test/expected/dist_backup.out deleted file mode 100644 index 00f5d79618a..00000000000 --- a/tsl/test/expected/dist_backup.out +++ /dev/null @@ -1,197 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------+------------------+--------------+------------------+------------------- - db_dist_backup_1 | db_dist_backup_1 | t | t | t - db_dist_backup_2 | db_dist_backup_2 | t | t | t - db_dist_backup_3 | db_dist_backup_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- Import testsupport.sql file to data nodes -\unset ECHO --- test NULL (STRICT function) -SELECT create_distributed_restore_point(NULL); - create_distributed_restore_point ----------------------------------- -(0 rows) - --- test long restore point name (>= 64 chars) -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('0123456789012345678901234567890123456789012345678901234567890123456789'); -WARNING: creating distributed restore point is deprecated -ERROR: restore point name is too long -\set ON_ERROR_STOP 1 --- test super user check -\set ON_ERROR_STOP 0 -SET ROLE :ROLE_1; -SELECT create_distributed_restore_point('test'); -WARNING: creating distributed restore point is deprecated -ERROR: must be superuser to create restore point -RESET ROLE; -\set ON_ERROR_STOP 1 --- make sure 2pc are enabled -SET timescaledb.enable_2pc = false; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -WARNING: creating distributed restore point is deprecated -ERROR: two-phase commit transactions are not enabled -\set ON_ERROR_STOP 1 -SET timescaledb.enable_2pc = true; -SHOW timescaledb.enable_2pc; - timescaledb.enable_2pc ------------------------- - on -(1 row) - --- make sure wal_level is replica or logical -SHOW wal_level; - wal_level ------------ - logical -(1 row) - --- make sure not in recovery mode -SELECT pg_is_in_recovery(); - pg_is_in_recovery -------------------- - f -(1 row) - --- test on single node (not part of a cluster) -CREATE DATABASE dist_rp_test; -\c dist_rp_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -ERROR: distributed restore point must be created on the access node -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE dist_rp_test WITH (FORCE); --- test on data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -WARNING: creating distributed restore point is deprecated -ERROR: distributed restore point must be created on the access node -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- test with distributed_exec() -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('SELECT create_distributed_restore_point(''test'')') -$$); -ERROR: [db_dist_backup_x]: distributed restore point must be created on the access node -\set ON_ERROR_STOP 1 --- test on access node -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('dist_rp') ORDER BY node_name; -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated - node_name | node_type | valid_lsn -------------------+-------------+----------- - db_dist_backup_1 | data_node | t - db_dist_backup_2 | data_node | t - db_dist_backup_3 | data_node | t - | access_node | t -(4 rows) - --- restore point can be have duplicates -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('dist_rp') ORDER BY node_name; -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated - node_name | node_type | valid_lsn -------------------+-------------+----------- - db_dist_backup_1 | data_node | t - db_dist_backup_2 | data_node | t - db_dist_backup_3 | data_node | t - | access_node | t -(4 rows) - --- make sure each new restore point have lsn greater then previous one (access node lsn) -SELECT restore_point as lsn_1 FROM create_distributed_restore_point('dist_rp_1') WHERE node_type = 'access_node' \gset -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -SELECT restore_point as lsn_2 FROM create_distributed_restore_point('dist_rp_2') WHERE node_type = 'access_node' \gset -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -SELECT pg_lsn(:'lsn_2') > pg_lsn(:'lsn_1') as valid_lsn; - valid_lsn ------------ - t -(1 row) - --- make sure it is compatible with local restore point -SELECT pg_create_restore_point('dist_rp') as lsn_3 \gset -SELECT pg_lsn(:'lsn_3') > pg_lsn(:'lsn_2') as valid_lsn; - valid_lsn ------------ - t -(1 row) - --- test create_distributed_restore_point() when one of the nodes if unavailable -SELECT alter_data_node(:'DATA_NODE_1', available => false); -WARNING: altering data node is deprecated - alter_data_node -------------------------------------------------------- - (db_dist_backup_1,localhost,55432,db_dist_backup_1,f) -(1 row) - -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -WARNING: creating distributed restore point is deprecated -ERROR: some data nodes are not available -\set ON_ERROR_STOP 1 -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node -------------------------------------------------------- - (db_dist_backup_1,localhost,55432,db_dist_backup_1,t) -(1 row) - -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('test') ORDER BY node_name; -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated -WARNING: creating distributed restore point is deprecated - node_name | node_type | valid_lsn -------------------+-------------+----------- - db_dist_backup_1 | data_node | t - db_dist_backup_2 | data_node | t - db_dist_backup_3 | data_node | t - | access_node | t -(4 rows) - -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_cagg.out b/tsl/test/expected/dist_cagg.out deleted file mode 100644 index ffba146d342..00000000000 --- a/tsl/test/expected/dist_cagg.out +++ /dev/null @@ -1,154 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -CREATE SCHEMA some_schema AUTHORIZATION :ROLE_1; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------+----------------+--------------+------------------+------------------- - db_dist_cagg_1 | db_dist_cagg_1 | t | t | t - db_dist_cagg_2 | db_dist_cagg_2 | t | t | t - db_dist_cagg_3 | db_dist_cagg_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- test alter_data_node(unvailable) with caggs --- --- create cagg on distributed hypertable -CREATE TABLE conditions_dist(day timestamptz NOT NULL, temperature INT NOT NULL); -SELECT create_distributed_hypertable('conditions_dist', 'day', chunk_time_interval => INTERVAL '1 day', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,conditions_dist,t) -(1 row) - -INSERT INTO conditions_dist(day, temperature) -SELECT ts, date_part('month', ts)*100 + date_part('day', ts) -FROM generate_series('2010-01-01 00:00:00 MSK' :: timestamptz, '2010-03-01 00:00:00 MSK' :: timestamptz - interval '1 day', '1 day') as ts; -CREATE MATERIALIZED VIEW conditions_dist_1m -WITH (timescaledb.continuous, timescaledb.materialized_only = false) AS -SELECT - timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket, - MIN(temperature), - MAX(temperature) -FROM conditions_dist -GROUP BY bucket; -NOTICE: refreshing continuous aggregate "conditions_dist_1m" -SELECT * FROM conditions_dist_1m ORDER BY bucket; - bucket | min | max -------------------------------+-----+------ - Thu Dec 31 13:00:00 2009 PST | 101 | 1231 - Sun Jan 31 13:00:00 2010 PST | 131 | 227 -(2 rows) - --- case 1: ensure select works when data node is unavailable -SELECT alter_data_node(:'DATA_NODE_1'); -WARNING: altering data node is deprecated - alter_data_node ---------------------------------------------------- - (db_dist_cagg_1,localhost,55432,db_dist_cagg_1,t) -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -WARNING: altering data node is deprecated - alter_data_node ---------------------------------------------------- - (db_dist_cagg_1,localhost,55433,db_dist_cagg_1,f) -(1 row) - -SELECT * FROM conditions_dist_1m ORDER BY bucket; - bucket | min | max -------------------------------+-----+------ - Thu Dec 31 13:00:00 2009 PST | 101 | 1231 - Sun Jan 31 13:00:00 2010 PST | 131 | 227 -(2 rows) - --- case 2: ensure cagg can use real-time aggregation while data node is not available -INSERT INTO conditions_dist(day, temperature) -SELECT ts, date_part('month', ts)*100 + date_part('day', ts) -FROM generate_series('2010-03-01 00:00:00 MSK' :: timestamptz, '2010-04-01 00:00:00 MSK' :: timestamptz - interval '1 day', '1 day') as ts; --- case 3: refreshing a cagg currently doesn't work when a data node is unavailable -\set ON_ERROR_STOP 0 -CALL refresh_continuous_aggregate('conditions_dist_1m', '2010-01-01', '2010-04-01'); -ERROR: could not connect to "db_dist_cagg_1" -\set ON_ERROR_STOP 1 --- case 4: ensure that new data is visible using real-time aggregation -SELECT * FROM conditions_dist_1m ORDER BY bucket; - bucket | min | max -------------------------------+-----+------ - Thu Dec 31 13:00:00 2009 PST | 101 | 1231 - Sun Jan 31 13:00:00 2010 PST | 131 | 227 - Sun Feb 28 13:00:00 2010 PST | 228 | 330 -(3 rows) - --- case 5: TRUNCATE will not work while data node is not available because invalidations are sent to the data nodes -\set ON_ERROR_STOP 0 -TRUNCATE TABLE conditions_dist; -ERROR: could not connect to "db_dist_cagg_1" -\set ON_ERROR_STOP 1 --- case 6: TRUNCATE cagg directly --- --- Fails because it is trying to send invalidation to DN. --- --- note: data in cagg is stored on AN, so the TRUNCATION itself doesn't fail, --- but it fails as a result of the failed invalidation. -\set ON_ERROR_STOP 0 -TRUNCATE conditions_dist_1m; -ERROR: could not connect to "db_dist_cagg_1" -\set ON_ERROR_STOP 1 --- case 7: ensure data node update works when it becomes available again -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -WARNING: altering data node is deprecated - alter_data_node ---------------------------------------------------- - (db_dist_cagg_1,localhost,55432,db_dist_cagg_1,f) -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node ---------------------------------------------------- - (db_dist_cagg_1,localhost,55432,db_dist_cagg_1,t) -(1 row) - -CALL refresh_continuous_aggregate('conditions_dist_1m', '2010-01-01', '2010-04-01'); -ALTER MATERIALIZED VIEW conditions_dist_1m SET(timescaledb.materialized_only = false); -SELECT * FROM conditions_dist_1m ORDER BY bucket; - bucket | min | max -------------------------------+-----+------ - Thu Dec 31 13:00:00 2009 PST | 101 | 1231 - Sun Jan 31 13:00:00 2010 PST | 131 | 227 - Sun Feb 28 13:00:00 2010 PST | 228 | 330 -(3 rows) - -ALTER MATERIALIZED VIEW conditions_dist_1m SET(timescaledb.materialized_only = true); -SELECT * FROM conditions_dist_1m ORDER BY bucket; - bucket | min | max -------------------------------+-----+------ - Thu Dec 31 13:00:00 2009 PST | 101 | 1231 - Sun Jan 31 13:00:00 2010 PST | 131 | 227 - Sun Feb 28 13:00:00 2010 PST | 228 | 330 -(3 rows) - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_commands.out b/tsl/test/expected/dist_commands.out deleted file mode 100644 index 5708895fdc3..00000000000 --- a/tsl/test/expected/dist_commands.out +++ /dev/null @@ -1,549 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------+--------------------+--------------+------------------+------------------- - db_dist_commands_1 | db_dist_commands_1 | t | t | t - db_dist_commands_2 | db_dist_commands_2 | t | t | t - db_dist_commands_3 | db_dist_commands_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -\des - List of foreign servers - Name | Owner | Foreign-data wrapper ---------------------+--------------------+---------------------- - db_dist_commands_1 | cluster_super_user | timescaledb_fdw - db_dist_commands_2 | cluster_super_user | timescaledb_fdw - db_dist_commands_3 | cluster_super_user | timescaledb_fdw -(3 rows) - -RESET ROLE; -CREATE FUNCTION _timescaledb_internal.invoke_distributed_commands() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_invoke_distributed_commands' -LANGUAGE C STRICT; -CREATE FUNCTION _timescaledb_internal.invoke_faulty_distributed_command() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_invoke_faulty_distributed_command' -LANGUAGE C STRICT; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT _timescaledb_internal.invoke_distributed_commands(); -INFO: db_dist_commands_1 result: PGRES_COMMAND_OK -INFO: db_dist_commands_2 result: PGRES_COMMAND_OK -INFO: db_dist_commands_3 result: PGRES_COMMAND_OK -INFO: db_dist_commands_1 result: PGRES_COMMAND_OK -INFO: db_dist_commands_2 result: PGRES_COMMAND_OK -INFO: db_dist_commands_1 result: PGRES_COMMAND_OK -INFO: db_dist_commands_2 result: PGRES_COMMAND_OK - invoke_distributed_commands ------------------------------ - -(1 row) - -\c :DATA_NODE_1 -\dt - List of relations - Schema | Name | Type | Owner ---------+------------+-------+------------- - public | disttable1 | table | test_role_1 - public | disttable2 | table | test_role_1 -(2 rows) - -SELECT * FROM disttable1; - time | device | temp -------------------------------+--------+------- - Sat Sep 18 00:00:00 1976 PDT | 47 | 103.4 -(1 row) - -\c :DATA_NODE_2 -\dt - List of relations - Schema | Name | Type | Owner ---------+------------+-------+------------- - public | disttable1 | table | test_role_1 - public | disttable2 | table | test_role_1 -(2 rows) - -SELECT * FROM disttable1; - time | device | temp -------------------------------+--------+------- - Sat Sep 18 00:00:00 1976 PDT | 47 | 103.4 -(1 row) - -\c :DATA_NODE_3 -\dt - List of relations - Schema | Name | Type | Owner ---------+------------+-------+------------- - public | disttable1 | table | test_role_1 -(1 row) - -SELECT * FROM disttable1; - time | device | temp -------+--------+------ -(0 rows) - -\c :TEST_DBNAME :ROLE_SUPERUSER -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Verify failed insert command gets fully rolled back -\set ON_ERROR_STOP 0 -SELECT _timescaledb_internal.invoke_faulty_distributed_command(); -ERROR: [db_dist_commands_3]: relation "public.disttable2" does not exist -\set ON_ERROR_STOP 1 -\c :DATA_NODE_1 -SELECT * from disttable2; - time | device | temp -------+--------+------ -(0 rows) - -\c :DATA_NODE_2 -SELECT * from disttable2; - time | device | temp -------+--------+------ -(0 rows) - --- Test connection session identity -\c :TEST_DBNAME :ROLE_SUPERUSER -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping --- Register_is_access_node_session_on_data_node() function and test that it returns false for --- connections openned by test suite. This simualates behaviour expected --- with a client connections. -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -\c :DATA_NODE_1 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - is_access_node_session_on_data_node -------------------------------------- - f -(1 row) - -\c :DATA_NODE_2 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - is_access_node_session_on_data_node -------------------------------------- - f -(1 row) - -\c :DATA_NODE_3 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - is_access_node_session_on_data_node -------------------------------------- - f -(1 row) - -\c :TEST_DBNAME :ROLE_SUPERUSER -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT is_access_node_session_on_data_node(); - is_access_node_session_on_data_node -------------------------------------- - f -(1 row) - --- Ensure peer dist id is already set and can be set only once -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT * FROM _timescaledb_functions.set_peer_dist_id('77348176-09da-4a80-bc78-e31bdf5e63ec'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_commands_1]: SELECT * FROM _timescaledb_functions.set_peer_dist_id('77348176-09da-4a80-bc78-e31bdf5e63ec') -ERROR: [db_dist_commands_1]: distributed peer ID already set -\set ON_ERROR_STOP 1 --- Repeat is_access_node_session_on_data_node() test again, but this time using connections openned from --- access node to data nodes. Must return true. -SELECT * FROM test.remote_exec(NULL, $$ SELECT is_access_node_session_on_data_node(); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_commands_1]: SELECT is_access_node_session_on_data_node() -NOTICE: [db_dist_commands_1]: -is_access_node_session_on_data_node ------------------------------------ -t -(1 row) - - -NOTICE: [db_dist_commands_2]: SELECT is_access_node_session_on_data_node() -NOTICE: [db_dist_commands_2]: -is_access_node_session_on_data_node ------------------------------------ -t -(1 row) - - -NOTICE: [db_dist_commands_3]: SELECT is_access_node_session_on_data_node() -NOTICE: [db_dist_commands_3]: -is_access_node_session_on_data_node ------------------------------------ -t -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test distributed_exec() --- Test calling distributed exec via direct function call -RESET ROLE; -CREATE OR REPLACE PROCEDURE distributed_exec_direct_function_call( - query TEXT, - node_list name[] = NULL, - transactional BOOLEAN = TRUE) -AS :TSL_MODULE_PATHNAME, 'ts_test_direct_function_call' LANGUAGE C; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Invalid input -\set ON_ERROR_STOP 0 -\set VERBOSITY default -BEGIN; --- Not allowed in transcation block if transactional=false -CALL distributed_exec_direct_function_call('CREATE TABLE dist_test(id int)', NULL, false); -ERROR: ts_dist_cmd_exec() cannot run inside a transaction block -ROLLBACK; --- multi-dimensional array of data nodes -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{{db_data_node_1}}'); -ERROR: invalid data nodes list -DETAIL: The array of data nodes cannot be multi-dimensional. --- Specified, but empty data node array -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{}'); -ERROR: invalid data nodes list -DETAIL: The array of data nodes cannot be empty. --- Specified, but contains null values -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{db_data_node_1, NULL}'); -ERROR: invalid data nodes list -DETAIL: The array of data nodes cannot contain null values. --- Specified, but not a data node -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{db_data_node_1928}'); -ERROR: server "db_data_node_1928" does not exist -\set VERBOSITY terse -\set ON_ERROR_STOP 1 --- Make sure dist session is properly set -CALL distributed_exec('DO $$ BEGIN ASSERT(SELECT is_access_node_session_on_data_node()) = true; END; $$;'); --- Test creating and dropping a table -CALL distributed_exec('CREATE TABLE dist_test (id int)'); -CALL distributed_exec('INSERT INTO dist_test values (7)'); --- Test INSERTING data using empty array of data nodes (same behavior as not specifying). -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from dist_test; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_commands_1]: SELECT * from dist_test -NOTICE: [db_dist_commands_1]: -id --- - 7 -(1 row) - - -NOTICE: [db_dist_commands_2]: SELECT * from dist_test -NOTICE: [db_dist_commands_2]: -id --- - 7 -(1 row) - - -NOTICE: [db_dist_commands_3]: SELECT * from dist_test -NOTICE: [db_dist_commands_3]: -id --- - 7 -(1 row) - - - remote_exec -------------- - -(1 row) - -CALL distributed_exec('DROP TABLE dist_test'); -\set ON_ERROR_STOP 0 -CALL distributed_exec('INSERT INTO dist_test VALUES (8)', ARRAY[:'DATA_NODE_1']); -ERROR: [db_dist_commands_1]: relation "dist_test" does not exist -\set ON_ERROR_STOP 1 --- Test creating and dropping a role -CREATE ROLE dist_test_role; --- Expect this to be an error, since data nodes are created on the same instance -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('CREATE ROLE dist_test_role'); -$$); -ERROR: [db_dist_commands_x]: role "dist_test_role" already exists -\set ON_ERROR_STOP 1 -SELECT * FROM test.remote_exec(NULL, $$ SELECT 1 from pg_catalog.pg_roles WHERE rolname = 'dist_test_role'; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_commands_1]: SELECT 1 from pg_catalog.pg_roles WHERE rolname = 'dist_test_role' -NOTICE: [db_dist_commands_1]: -?column? --------- - 1 -(1 row) - - -NOTICE: [db_dist_commands_2]: SELECT 1 from pg_catalog.pg_roles WHERE rolname = 'dist_test_role' -NOTICE: [db_dist_commands_2]: -?column? --------- - 1 -(1 row) - - -NOTICE: [db_dist_commands_3]: SELECT 1 from pg_catalog.pg_roles WHERE rolname = 'dist_test_role' -NOTICE: [db_dist_commands_3]: -?column? --------- - 1 -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP ROLE DIST_TEST_ROLE; -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('DROP ROLE dist_test_role'); -$$); -ERROR: [db_dist_commands_x]: role "dist_test_role" does not exist -\set ON_ERROR_STOP 1 --- Do not allow to run distributed_exec() on a data nodes -\c :DATA_NODE_1 -\set ON_ERROR_STOP 0 -CALL distributed_exec('SELECT 1'); -ERROR: function must be run on the access node only -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_SUPERUSER --- Test health check function output on access node -SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST; - node_name | healthy | in_recovery | error ---------------------+---------+-------------+------- - | t | f | - db_dist_commands_1 | t | f | - db_dist_commands_2 | t | f | - db_dist_commands_3 | t | f | -(4 rows) - -SELECT * FROM delete_data_node(:'DATA_NODE_1'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node(:'DATA_NODE_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node(:'DATA_NODE_3'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- Test health check when no longer an access node (no data nodes) -SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST; - node_name | healthy | in_recovery | error ------------+---------+-------------+------- - | t | f | -(1 row) - -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); -\set ON_ERROR_STOP 0 --- Calling distributed_exec without data nodes should fail -CALL distributed_exec('SELECT 1'); -ERROR: function must be run on the access node only -CALL distributed_exec('SELECT 1', '{data_node_1}'); -ERROR: function must be run on the access node only -\set ON_ERROR_STOP 1 --- Test TS execution on non-TSDB server -CREATE EXTENSION postgres_fdw; -CREATE SERVER myserver FOREIGN DATA WRAPPER postgres_fdw - OPTIONS (host 'foo', dbname 'foodb', port '5432'); -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec('{myserver}', $$ SELECT 1; $$); -WARNING: executing remote command is deprecated -ERROR: data node "myserver" is not a TimescaleDB server -\set ON_ERROR_STOP 1 -DROP SERVER myserver; -DROP EXTENSION postgres_fdw; --- Test that transactional behaviour is the default and that it can be --- disabled. --- --- In this case, we only execute it on one data node since we are --- creating a database and multiple creations of the database would --- clash when executed on the same instace. --- --- We prefix the database names with the test file to be able to --- parallelize the test. Not possible right now because there are --- other databases above that prevents this. -\c :TEST_DBNAME :ROLE_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('dist_commands_1', host => 'localhost', database => :'DATA_NODE_1'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+--------------------+--------------+------------------+------------------- - dist_commands_1 | db_dist_commands_1 | t | t | t -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('dist_commands_2', host => 'localhost', database => :'DATA_NODE_2'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+--------------------+--------------+------------------+------------------- - dist_commands_2 | db_dist_commands_2 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER dist_commands_1, dist_commands_2 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -\set ON_ERROR_STOP 0 -CALL distributed_exec('CREATE DATABASE dist_commands_magic', - node_list => '{dist_commands_1}'); -ERROR: [dist_commands_1]: CREATE DATABASE cannot run inside a transaction block -\set ON_ERROR_STOP 1 -CALL distributed_exec('CREATE DATABASE dist_commands_magic', - node_list => '{dist_commands_1}', transactional => FALSE); -DROP DATABASE dist_commands_magic WITH (FORCE); --- Test that distributed_exec honor the 2PC behaviour when starting a --- transaction locally. It should also give an error if attempting to --- execute non-transactionally inside a local transaction. --- To test that distributed_exec honors transactions, we create a --- table on both data nodes, and then tweak one of the tables so that --- we get a duplicate key when updating the table on both data --- nodes. This should then abort the transaction on all data nodes. -\c :TEST_DBNAME :ROLE_1 -CALL distributed_exec($$ - CREATE TABLE my_table (key INT, value TEXT, PRIMARY KEY (key)); -$$); -\c :DATA_NODE_1 -INSERT INTO my_table VALUES (1, 'foo'); -\c :TEST_DBNAME :ROLE_1 -\set ON_ERROR_STOP 0 -BEGIN; -CALL distributed_exec($$ INSERT INTO my_table VALUES (1, 'bar') $$); -ERROR: [dist_commands_1]: duplicate key value violates unique constraint "my_table_pkey" -COMMIT; -\set ON_ERROR_STOP 1 --- No changes should be there -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); -WARNING: executing remote command is deprecated -NOTICE: [dist_commands_1]: SELECT * FROM my_table -NOTICE: [dist_commands_1]: -key|value ----+----- - 1|foo -(1 row) - - -NOTICE: [dist_commands_2]: SELECT * FROM my_table -NOTICE: [dist_commands_2]: -key|value ----+----- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- This should work. -BEGIN; -CALL distributed_exec($$ INSERT INTO my_table VALUES (2, 'bar'); $$); -COMMIT; --- We should see changes -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); -WARNING: executing remote command is deprecated -NOTICE: [dist_commands_1]: SELECT * FROM my_table -NOTICE: [dist_commands_1]: -key|value ----+----- - 1|foo - 2|bar -(2 rows) - - -NOTICE: [dist_commands_2]: SELECT * FROM my_table -NOTICE: [dist_commands_2]: -key|value ----+----- - 2|bar -(1 row) - - - remote_exec -------------- - -(1 row) - --- This should fail since we are inside a transaction and asking for --- transactional execution on the remote nodes. Non-transactional --- execution should be outside transactions. -\set ON_ERROR_STOP 0 -BEGIN; -CALL distributed_exec( - $$ INSERT INTO my_table VALUES (3, 'baz') $$, - transactional => FALSE -); -ERROR: distributed_exec() cannot run inside a transaction block -COMMIT; -\set ON_ERROR_STOP 1 --- We should see no changes -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); -WARNING: executing remote command is deprecated -NOTICE: [dist_commands_1]: SELECT * FROM my_table -NOTICE: [dist_commands_1]: -key|value ----+----- - 1|foo - 2|bar -(2 rows) - - -NOTICE: [dist_commands_2]: SELECT * FROM my_table -NOTICE: [dist_commands_2]: -key|value ----+----- - 2|bar -(1 row) - - - remote_exec -------------- - -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); diff --git a/tsl/test/expected/dist_compression-13.out b/tsl/test/expected/dist_compression-13.out deleted file mode 100644 index 563deec8608..00000000000 --- a/tsl/test/expected/dist_compression-13.out +++ /dev/null @@ -1,1776 +0,0 @@ --- 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. ---------------------------------------------------- --- Test compression on a distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -\ir include/compression_utils.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 ECHO errors -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_compression_1 | db_dist_compression_1 | t | t | t - db_dist_compression_2 | db_dist_compression_2 | t | t | t - db_dist_compression_3 | db_dist_compression_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE compressed(time timestamptz, device int, temp float); --- Replicate twice to see that compress_chunk compresses all replica chunks -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (1,public,compressed,t) -(1 row) - -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -\x -SELECT * FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; --[ RECORD 1 ]------------+------------------------- -id | 1 -schema_name | public -table_name | compressed -associated_schema_name | _timescaledb_internal -associated_table_prefix | _dist_hyper_1 -num_dimensions | 2 -chunk_sizing_func_schema | _timescaledb_functions -chunk_sizing_func_name | calculate_chunk_interval -chunk_target_size | 0 -compression_state | 1 -compressed_hypertable_id | -replication_factor | 2 -status | 0 - -\x -SELECT test.remote_exec(NULL, $$ -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_1]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_2]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_2]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_3]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_3]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - --- There should be no compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Test that compression is rolled back on aborted transaction -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Data nodes should now report compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Abort the transaction -ROLLBACK; --- No compressed chunks since we rolled back -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Compress for real this time -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Check that one chunk, and its replica, is compressed -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - -select * from hypertable_compression_stats('compressed'); - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - 2 | 1 | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - 2 | 0 | | | | | | | | | db_dist_compression_3 - 2 | 1 | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 -(3 rows) - ---- Decompress the chunk and replica -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Compress odd numbered chunks -SELECT compress_chunk(chunk) FROM -( - SELECT *, row_number() OVER () AS rownum - FROM show_chunks('compressed') AS chunk - ORDER BY chunk -) AS t -WHERE rownum % 2 = 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(2 rows) - -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_3 -(6 rows) - --- Compress twice to notice idempotent operation -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Compress again to verify errors are ignored -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- There should be no uncompressed chunks -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 | db_dist_compression_3 -(6 rows) - -SELECT test.remote_exec(NULL, $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_1]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_2]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_3]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 4|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 3|f | 1|f - 3| 2|_timescaledb_internal|compress_hyper_2_3_chunk| |f | 0|f - 4| 2|_timescaledb_internal|compress_hyper_2_4_chunk| |f | 0|f -(4 rows) - - - remote_exec -------------- - -(1 row) - --- Decompress the chunks and replicas -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Should now be decompressed -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Decompress twice to generate NOTICE that the chunk is already decompressed -SELECT decompress_chunk(chunk, if_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; -NOTICE: chunk "_dist_hyper_1_1_chunk" is not compressed - decompress_chunk ------------------- - -(1 row) - -\x -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'compressed'; --[ RECORD 1 ]-------+-------------------------------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -owner | test_role_1 -num_dimensions | 2 -num_chunks | 3 -compression_enabled | t -is_distributed | t -replication_factor | 2 -data_nodes | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -tablespaces | - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; --[ RECORD 1 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_1_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_2} --[ RECORD 2 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_2_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_2,db_dist_compression_3} --[ RECORD 3 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_3_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_3} - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; --[ RECORD 1 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 1 -column_name | time -column_type | timestamp with time zone -dimension_type | Time -time_interval | @ 7 days -integer_interval | -integer_now_func | -num_partitions | --[ RECORD 2 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 2 -column_name | device -column_type | integer -dimension_type | Space -time_interval | -integer_interval | -integer_now_func | -num_partitions | 3 - -\x -SELECT * FROM chunks_detailed_size('compressed'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('compressed'::regclass) ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------------- - 16384 | 81920 | 0 | 98304 | db_dist_compression_1 - 16384 | 81920 | 0 | 98304 | db_dist_compression_2 - 16384 | 81920 | 0 | 98304 | db_dist_compression_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - --- Disable compression on distributed table tests -ALTER TABLE compressed SET (timescaledb.compress = false); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 0 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- -(0 rows) - ---Now re-enable compression -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT chunk_name, node_name, compression_status -FROM chunk_compression_stats('compressed') -ORDER BY 1, 2; - chunk_name | node_name | compression_status ------------------------+-----------------------+-------------------- - _dist_hyper_1_1_chunk | db_dist_compression_1 | Compressed - _dist_hyper_1_1_chunk | db_dist_compression_2 | Compressed - _dist_hyper_1_2_chunk | db_dist_compression_2 | Uncompressed - _dist_hyper_1_2_chunk | db_dist_compression_3 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_1 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_3 | Uncompressed -(6 rows) - --- ALTER TABLE on distributed compressed hypertable -ALTER TABLE compressed ADD COLUMN new_coli integer; -ALTER TABLE compressed ADD COLUMN new_colv varchar(30); -SELECT * FROM _timescaledb_catalog.hypertable_compression -ORDER BY attname; - hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst ----------------+----------+--------------------------+------------------------+----------------------+-------------+-------------------- - 1 | device | 0 | 1 | | | - 1 | new_coli | 4 | | | | - 1 | new_colv | 2 | | | | - 1 | temp | 3 | | | | - 1 | time | 4 | | 1 | f | t -(5 rows) - -SELECT count(*) from compressed where new_coli is not null; - count -------- - 0 -(1 row) - ---insert data into new chunk -INSERT INTO compressed -SELECT '2019-08-01 00:00', 100, 100, 1, 'newcolv' ; -SELECT count(compress_chunk(ch,true)) FROM show_chunks('compressed') ch; - count -------- - 4 -(1 row) - -SELECT * from compressed where new_coli is not null; - time | device | temp | new_coli | new_colv -------------------------------+--------+------+----------+---------- - Thu Aug 01 00:00:00 2019 PDT | 100 | 100 | 1 | newcolv -(1 row) - --- Test ALTER TABLE rename column on distributed hypertables -ALTER TABLE compressed RENAME new_coli TO new_intcol ; -ALTER TABLE compressed RENAME device TO device_id ; -SELECT * FROM test.remote_exec( NULL, - $$ SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname; $$ ); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_1]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_2]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_3]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- TEST insert data into compressed chunk -INSERT INTO compressed -SELECT '2019-08-01 01:00', 300, 300, 3, 'newcolv' ; -SELECT * from compressed where new_intcol = 3; - time | device_id | temp | new_intcol | new_colv -------------------------------+-----------+------+------------+---------- - Thu Aug 01 01:00:00 2019 PDT | 300 | 300 | 3 | newcolv -(1 row) - --- We're done with the table, so drop it. -DROP TABLE IF EXISTS compressed CASCADE; ------------------------------------------------------- --- Test compression policy on a distributed hypertable ------------------------------------------------------- -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - location2 char(10) NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL - ); -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => '31days'::interval, replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,conditions,t) -(1 row) - ---TEST 1-- ---cannot set policy without enabling compression -- -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression not enabled on hypertable "conditions" -\set ON_ERROR_STOP 1 --- TEST2 -- ---add a policy to compress chunks -- -alter table conditions set (timescaledb.compress, timescaledb.compress_segmentby = 'location', timescaledb.compress_orderby = 'time'); -insert into conditions -select generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '1 day'), 'POR', 'klick', 55, 75; -select add_compression_policy('conditions', '60d'::interval) AS compressjob_id -\gset -select * from _timescaledb_config.bgw_job where id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - -select * from alter_job(:compressjob_id, schedule_interval=>'1s'); - job_id | schedule_interval | max_runtime | max_retries | retry_period | scheduled | config | next_start | check_config | fixed_schedule | initial_start | timezone ---------+-------------------+-------------+-------------+--------------+-----------+-----------------------------------------------------+------------+-------------------------------------------------+----------------+---------------+---------- - 1000 | @ 1 sec | @ 0 | -1 | @ 1 hour | t | {"hypertable_id": 2, "compress_after": "@ 60 days"} | -infinity | _timescaledb_functions.policy_compression_check | f | | -(1 row) - -select * from _timescaledb_config.bgw_job where id >= 1000 ORDER BY id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 1 sec | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - --- we want only 1 chunk to be compressed -- -SELECT alter_job(id,config:=jsonb_set(config,'{maxchunks_to_compress}', '1')) -FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - alter_job ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - (1000,"@ 1 sec","@ 0",-1,"@ 1 hour",t,"{""hypertable_id"": 2, ""compress_after"": ""@ 60 days"", ""maxchunks_to_compress"": 1}",-infinity,_timescaledb_functions.policy_compression_check,f,,) -(1 row) - -insert into conditions -select now()::timestamp, 'TOK', 'sony', 55, 75; --- TEST3 -- ---only the old chunks will get compressed when policy is executed-- -CALL run_job(:compressjob_id); -select chunk_name, node_name, pg_size_pretty(before_compression_total_bytes) before_total, -pg_size_pretty( after_compression_total_bytes) after_total -from chunk_compression_stats('conditions') where compression_status like 'Compressed' order by chunk_name; - chunk_name | node_name | before_total | after_total ------------------------+-----------------------+--------------+------------- - _dist_hyper_2_6_chunk | db_dist_compression_1 | 32 kB | 32 kB - _dist_hyper_2_6_chunk | db_dist_compression_3 | 32 kB | 32 kB -(2 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 6 | 2 | _timescaledb_internal | _dist_hyper_2_6_chunk | | f | 1 | f - 7 | 2 | _timescaledb_internal | _dist_hyper_2_7_chunk | | f | 0 | f - 8 | 2 | _timescaledb_internal | _dist_hyper_2_8_chunk | | f | 0 | f -(3 rows) - --- TEST 4 -- ---cannot set another policy -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval, if_not_exists=>true); -NOTICE: compression policy already exists for hypertable "conditions", skipping - add_compression_policy ------------------------- - -1 -(1 row) - -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression policy already exists for hypertable or continuous aggregate "conditions" -select add_compression_policy('conditions', '30d'::interval, if_not_exists=>true); -WARNING: compression policy already exists for hypertable "conditions" - add_compression_policy ------------------------- - -1 -(1 row) - -\set ON_ERROR_STOP 1 ---TEST 5 -- --- drop the policy -- -select remove_compression_policy('conditions'); - remove_compression_policy ---------------------------- - t -(1 row) - -select count(*) from _timescaledb_config.bgw_job WHERE id>=1000; - count -------- - 0 -(1 row) - ---TEST 6 -- --- try to execute the policy after it has been dropped -- -\set ON_ERROR_STOP 0 -CALL run_job(:compressjob_id); -ERROR: job 1000 not found -\set ON_ERROR_STOP 1 --- We're done with the table, so drop it. -DROP TABLE IF EXISTS conditions CASCADE; ---TEST 7 ---compression policy for smallint, integer or bigint based partition hypertable ---smallint tests -CREATE TABLE test_table_smallint(time smallint, val int); -SELECT create_distributed_hypertable('test_table_smallint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ----------------------------------- - (3,public,test_table_smallint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT' -$$); -SELECT set_integer_now_func('test_table_smallint', 'dummy_now_smallint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_smallint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_smallint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_smallint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1001 | Compression Policy [1001] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 3 | {"hypertable_id": 3, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_smallint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_3_10_chunk | db_dist_compression_2 | 24576 | 16384 - _dist_hyper_3_10_chunk | db_dist_compression_3 | 24576 | 16384 - _dist_hyper_3_9_chunk | db_dist_compression_1 | 24576 | 16384 - _dist_hyper_3_9_chunk | db_dist_compression_2 | 24576 | 16384 -(4 rows) - ---integer tests -CREATE TABLE test_table_integer(time int, val int); -SELECT create_distributed_hypertable('test_table_integer', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ---------------------------------- - (4,public,test_table_integer,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER' -$$); -SELECT set_integer_now_func('test_table_integer', 'dummy_now_integer'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_integer SELECT generate_series(1,5), 10; -ALTER TABLE test_table_integer SET (timescaledb.compress); -SELECT add_compression_policy('test_table_integer', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 4 | {"hypertable_id": 4, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_integer') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_4_14_chunk | db_dist_compression_2 | 24576 | 16384 - _dist_hyper_4_14_chunk | db_dist_compression_3 | 24576 | 16384 - _dist_hyper_4_15_chunk | db_dist_compression_1 | 24576 | 16384 - _dist_hyper_4_15_chunk | db_dist_compression_3 | 24576 | 16384 -(4 rows) - ---bigint tests -CREATE TABLE test_table_bigint(time bigint, val int); -SELECT create_distributed_hypertable('test_table_bigint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable --------------------------------- - (5,public,test_table_bigint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT' -$$); -SELECT set_integer_now_func('test_table_bigint', 'dummy_now_bigint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_bigint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_bigint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_bigint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1003 | Compression Policy [1003] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 5 | {"hypertable_id": 5, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_bigint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_5_19_chunk | db_dist_compression_1 | 24576 | 16384 - _dist_hyper_5_19_chunk | db_dist_compression_3 | 24576 | 16384 - _dist_hyper_5_20_chunk | db_dist_compression_1 | 24576 | 16384 - _dist_hyper_5_20_chunk | db_dist_compression_2 | 24576 | 16384 -(4 rows) - ---TEST8 insert into compressed chunks on dist. hypertable -CREATE TABLE test_recomp_int(time bigint, val int); -SELECT create_distributed_hypertable('test_recomp_int', 'time', chunk_time_interval => 20); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (6,public,test_recomp_int,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT' -$$); -select set_integer_now_func('test_recomp_int', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - -insert into test_recomp_int select generate_series(1,5), 10; -alter table test_recomp_int set (timescaledb.compress); -CREATE VIEW test_recomp_int_chunk_status as -SELECT - c.table_name as chunk_name, - c.status as chunk_status -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int'; ---compress chunks -SELECT compress_chunk(chunk) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - ---check the status -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - --- insert into compressed chunks of test_recomp_int (using same value for val)-- -insert into test_recomp_int select 10, 10; -SELECT count(*) from test_recomp_int where val = 10; - count -------- - 6 -(1 row) - ---chunk status should change --- -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - -SELECT -c.schema_name || '.' || c.table_name as "CHUNK_NAME" -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' \gset ---call recompress_chunk directly on distributed chunk -CALL recompress_chunk(:'CHUNK_NAME'::regclass); ---check chunk status now, should be compressed -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - -SELECT count(*) from test_recomp_int; - count -------- - 6 -(1 row) - ---add a policy-- -select add_compression_policy('test_recomp_int', 1::int) AS compressjob_id -\gset ---once again add data to the compressed chunk -insert into test_recomp_int select generate_series(5,7), 10; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - ---run the compression policy job, it will recompress chunks that are unordered -CALL run_job(:compressjob_id); -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - -RESET timescaledb.enable_per_data_node_queries; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - ----run copy tests ---copy data into existing chunk + for a new chunk -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT time_bucket(20, time ), count(*) -FROM test_recomp_int -GROUP BY time_bucket( 20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 12 - 100 | 3 -(2 rows) - ---another new chunk -INSERT INTO test_recomp_int VALUES( 65, 10); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 0 - _dist_hyper_6_26_chunk | 0 -(3 rows) - ---compress all 3 chunks --- ---check status, unordered chunk status will not change -SELECT compress_chunk(chunk, true) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk - _timescaledb_internal._dist_hyper_6_25_chunk - _timescaledb_internal._dist_hyper_6_26_chunk -(3 rows) - -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---interleave copy into 3 different chunks and check status-- -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 9 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - -RESET timescaledb.enable_per_data_node_queries; ---check compression_status afterwards-- -CALL recompress_all_chunks('test_recomp_int', 2, true); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -CALL run_job(:compressjob_id); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---verify that there are no errors if the policy/recompress_chunk is executed again ---on previously compressed chunks -CALL run_job(:compressjob_id); -CALL recompress_all_chunks('test_recomp_int', true); -NOTICE: nothing to recompress in chunk "_dist_hyper_6_24_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_25_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_26_chunk" ---decompress and recompress chunk -\set ON_ERROR_STOP 0 -SELECT decompress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - decompress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CALL recompress_all_chunks('test_recomp_int', 1, false); -ERROR: call compress_chunk instead of recompress_chunk -\set ON_ERROR_STOP 1 --- test alter column type with distributed hypertable -\set ON_ERROR_STOP 0 -ALTER TABLE test_table_smallint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_integer ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_bigint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -\set ON_ERROR_STOP 1 ---create a cont agg view on the ht with compressed chunks as well -SELECT compress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CREATE MATERIALIZED VIEW test_recomp_int_cont_view -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS SELECT time_bucket(BIGINT '5', "time"), SUM(val) - FROM test_recomp_int - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_recomp_int_cont_view', NULL, BIGINT '5', '1 day'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1005 -(1 row) - -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, NULL); -SELECT * FROM test_recomp_int ORDER BY 1; - time | val -------+----- - 1 | 10 - 2 | 10 - 3 | 10 - 4 | 10 - 5 | 10 - 5 | 10 - 6 | 10 - 7 | 10 - 10 | 10 - 11 | 11 - 12 | 12 - 13 | 13 - 14 | 14 - 15 | 15 - 65 | 10 - 66 | 66 - 70 | 70 - 100 | 100 - 101 | 100 - 102 | 100 - 103 | 100 - 104 | 100 -(22 rows) - -SELECT * FROM test_recomp_int_cont_view ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 - 5 | 40 - 10 | 60 - 15 | 15 - 65 | 76 - 70 | 70 - 100 | 500 -(7 rows) - ---TEST cagg triggers work on distributed hypertables when we insert into --- compressed chunks. -SELECT -CASE WHEN compress_chunk(chunk, true) IS NOT NULL THEN 'compress' END AS ch - FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk )q; - ch ----------- - compress - compress - compress -(3 rows) - -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 -(1 row) - ---insert into an existing compressed chunk and a new chunk -SET timescaledb.enable_distributed_insert_with_copy=false; -INSERT INTO test_recomp_int VALUES (1, 10), (2,10), (3, 10); -INSERT INTO test_recomp_int VALUES(51, 10); ---refresh the cagg and verify the new results -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 70 - 50 | 10 -(2 rows) - ---repeat test with copy setting turned to true -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO test_recomp_int VALUES (4, 10); -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 80 - 50 | 10 -(2 rows) - ---TEST drop one of the compressed chunks in test_recomp_int. The catalog ---tuple for the chunk will be preserved since we have a cagg. --- Verify that status is accurate. -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 9 | f | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - -SELECT drop_chunks('test_recomp_int', older_than=> 20::bigint ); - drop_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 0 | t | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - --- TEST drop should nuke everything -DROP TABLE test_recomp_int CASCADE; -NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to table _timescaledb_internal._hyper_7_27_chunk --- test compression default handling -CREATE TABLE test_defaults(time timestamptz NOT NULL, device_id int); -SELECT create_distributed_hypertable('test_defaults','time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (8,public,test_defaults,t) -(1 row) - -ALTER TABLE test_defaults SET (timescaledb.compress,timescaledb.compress_segmentby='device_id'); --- create 2 chunks -INSERT INTO test_defaults SELECT '2000-01-01', 1; -INSERT INTO test_defaults SELECT '2001-01-01', 1; --- compress first chunk -SELECT compress_chunk(show_chunks) AS compressed_chunk FROM show_chunks('test_defaults') ORDER BY show_chunks::text LIMIT 1; - compressed_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_8_29_chunk -(1 row) - -SELECT * FROM test_defaults ORDER BY 1; - time | device_id -------------------------------+----------- - Sat Jan 01 00:00:00 2000 PST | 1 - Mon Jan 01 00:00:00 2001 PST | 1 -(2 rows) - -ALTER TABLE test_defaults ADD COLUMN c1 int; -ALTER TABLE test_defaults ADD COLUMN c2 int NOT NULL DEFAULT 42; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(2 rows) - --- try insert into compressed and recompress -INSERT INTO test_defaults SELECT '2000-01-01', 2; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - -CALL recompress_all_chunks('test_defaults', 1, false); -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - --- test dropping columns from compressed -CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); -SELECT create_distributed_hypertable('test_drop','time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (9,public,test_drop,t) -(1 row) - -ALTER TABLE test_drop SET (timescaledb.compress,timescaledb.compress_segmentby='device',timescaledb.compress_orderby='o1,o2'); --- switch to WARNING only to suppress compress_chunk NOTICEs -SET client_min_messages TO WARNING; --- create some chunks each with different physical layout -ALTER TABLE test_drop DROP COLUMN f1; -INSERT INTO test_drop SELECT NULL,NULL,'2000-01-01',1,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 1 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f2; --- test non-existant column -\set ON_ERROR_STOP 0 -ALTER TABLE test_drop DROP COLUMN f10; -ERROR: column "f10" of relation "test_drop" does not exist -\set ON_ERROR_STOP 1 -ALTER TABLE test_drop DROP COLUMN IF EXISTS f10; -INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 2 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f3; -INSERT INTO test_drop SELECT '2003-01-01',3,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 3 -(1 row) - -ALTER TABLE test_drop ADD COLUMN c1 TEXT; -ALTER TABLE test_drop ADD COLUMN c2 TEXT; -INSERT INTO test_drop SELECT '2004-01-01',4,'o1','o2','c1','c2-4'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 4 -(1 row) - -ALTER TABLE test_drop DROP COLUMN c1; -INSERT INTO test_drop SELECT '2005-01-01',5,'o1','o2','c2-5'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 5 -(1 row) - -RESET client_min_messages; -SELECT * FROM test_drop ORDER BY 1; - time | device | o1 | o2 | c2 -------------------------------+--------+----+----+------ - Sat Jan 01 00:00:00 2000 PST | 1 | o1 | o2 | - Mon Jan 01 00:00:00 2001 PST | 2 | o1 | o2 | - Wed Jan 01 00:00:00 2003 PST | 3 | o1 | o2 | - Thu Jan 01 00:00:00 2004 PST | 4 | o1 | o2 | c2-4 - Sat Jan 01 00:00:00 2005 PST | 5 | o1 | o2 | c2-5 -(5 rows) - --- check dropped columns got removed from catalog --- only c2 should be left in metadata -SELECT attname -FROM _timescaledb_catalog.hypertable_compression htc -INNER JOIN _timescaledb_catalog.hypertable ht - ON ht.id=htc.hypertable_id AND ht.table_name='test_drop' -WHERE attname NOT IN ('time','device','o1','o2') -ORDER BY 1; - attname ---------- - c2 -(1 row) - --- test ADD COLUMN IF NOT EXISTS on a distributed hypertable -CREATE TABLE metric (time TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL); -SELECT create_distributed_hypertable('metric', 'time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (10,public,metric,t) -(1 row) - -ALTER TABLE metric SET ( -timescaledb.compress, -timescaledb.compress_segmentby = 'dev_id', -timescaledb.compress_orderby = 'time DESC' -); -INSERT INTO metric(time, val, dev_id) -SELECT s.*, 3.14+1, 1 -FROM generate_series('2021-07-01 00:00:00'::timestamp, - '2021-08-17 00:02:00'::timestamp, '30 s'::interval) s; -SELECT compress_chunk(chunk) -FROM show_chunks('metric') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_36_chunk - _timescaledb_internal._dist_hyper_10_37_chunk - _timescaledb_internal._dist_hyper_10_38_chunk - _timescaledb_internal._dist_hyper_10_39_chunk - _timescaledb_internal._dist_hyper_10_40_chunk - _timescaledb_internal._dist_hyper_10_41_chunk - _timescaledb_internal._dist_hyper_10_42_chunk -(7 rows) - --- make sure we have chunks on all data nodes -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks where hypertable_name like 'metric'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-------------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+------------------------- - public | metric | _timescaledb_internal | _dist_hyper_10_36_chunk | time | timestamp with time zone | Wed Jun 30 17:00:00 2021 PDT | Wed Jul 07 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_37_chunk | time | timestamp with time zone | Wed Jul 07 17:00:00 2021 PDT | Wed Jul 14 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_38_chunk | time | timestamp with time zone | Wed Jul 14 17:00:00 2021 PDT | Wed Jul 21 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_39_chunk | time | timestamp with time zone | Wed Jul 21 17:00:00 2021 PDT | Wed Jul 28 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_40_chunk | time | timestamp with time zone | Wed Jul 28 17:00:00 2021 PDT | Wed Aug 04 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_41_chunk | time | timestamp with time zone | Wed Aug 04 17:00:00 2021 PDT | Wed Aug 11 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_42_chunk | time | timestamp with time zone | Wed Aug 11 17:00:00 2021 PDT | Wed Aug 18 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} -(7 rows) - --- perform all combinations --- [IF NOT EXISTS] - [] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; --- [IF NOT EXISTS] - ["medium"] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; -NOTICE: column "medium" of relation "metric" already exists, skipping --- [] - [] -ALTER TABLE metric ADD COLUMN "medium_1" varchar; --- [] - ["medium_1"] -\set ON_ERROR_STOP 0 -ALTER TABLE metric ADD COLUMN "medium_1" varchar; -ERROR: column "medium_1" of relation "metric" already exists -SELECT * FROM metric limit 5; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+--------+---------- - Wed Jul 21 16:59:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:59:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:57:30 2021 PDT | 4.14 | 1 | | -(5 rows) - -SELECT * FROM metric where medium is not null; - time | val | dev_id | medium | medium_1 -------+-----+--------+--------+---------- -(0 rows) - --- INSERTs operate normally on the added column -INSERT INTO metric (time, val, dev_id, medium) -SELECT s.*, 3.14+1, 1, 'medium_value_text' -FROM generate_series('2021-08-18 00:00:00'::timestamp, - '2021-08-19 00:02:00'::timestamp, '30 s'::interval) s; -SELECT * FROM metric where medium is not null ORDER BY time LIMIT 1; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+-------------------+---------- - Wed Aug 18 00:00:00 2021 PDT | 4.14 | 1 | medium_value_text | -(1 row) - --- test alter_data_node(unvailable) with compressed chunks --- --- create compressed distributed hypertable -CREATE TABLE compressed(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (11,public,compressed,t) -(1 row) - --- insert data and get chunks distribution -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+--------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT count(*) FROM compressed; - count -------- - 49 -(1 row) - --- make data node unavailable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 5 chunks - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55433,db_dist_compression_1,f) -(1 row) - -SET ROLE :ROLE_1; --- update compressed chunks -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; --- ensure that chunks associated with unavailable data node 1 --- are removed after being updated -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+----------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2', :'DATA_NODE_3'], $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- make data node available again -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,f) -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,t) -(1 row) - -SET ROLE :ROLE_1; --- ensure that stale chunks being dropped from data node 1 automatically -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- recompress chunks -CALL recompress_all_chunks('compressed', 3, true); -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE compressed; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_compression-14.out b/tsl/test/expected/dist_compression-14.out deleted file mode 100644 index 56b481eba7c..00000000000 --- a/tsl/test/expected/dist_compression-14.out +++ /dev/null @@ -1,1776 +0,0 @@ --- 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. ---------------------------------------------------- --- Test compression on a distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -\ir include/compression_utils.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 ECHO errors -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_compression_1 | db_dist_compression_1 | t | t | t - db_dist_compression_2 | db_dist_compression_2 | t | t | t - db_dist_compression_3 | db_dist_compression_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE compressed(time timestamptz, device int, temp float); --- Replicate twice to see that compress_chunk compresses all replica chunks -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (1,public,compressed,t) -(1 row) - -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -\x -SELECT * FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; --[ RECORD 1 ]------------+------------------------- -id | 1 -schema_name | public -table_name | compressed -associated_schema_name | _timescaledb_internal -associated_table_prefix | _dist_hyper_1 -num_dimensions | 2 -chunk_sizing_func_schema | _timescaledb_functions -chunk_sizing_func_name | calculate_chunk_interval -chunk_target_size | 0 -compression_state | 1 -compressed_hypertable_id | -replication_factor | 2 -status | 0 - -\x -SELECT test.remote_exec(NULL, $$ -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_1]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_2]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_2]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_3]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_3]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - --- There should be no compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Test that compression is rolled back on aborted transaction -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Data nodes should now report compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Abort the transaction -ROLLBACK; --- No compressed chunks since we rolled back -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Compress for real this time -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Check that one chunk, and its replica, is compressed -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - -select * from hypertable_compression_stats('compressed'); - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - 2 | 1 | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - 2 | 0 | | | | | | | | | db_dist_compression_3 - 2 | 1 | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 -(3 rows) - ---- Decompress the chunk and replica -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Compress odd numbered chunks -SELECT compress_chunk(chunk) FROM -( - SELECT *, row_number() OVER () AS rownum - FROM show_chunks('compressed') AS chunk - ORDER BY chunk -) AS t -WHERE rownum % 2 = 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(2 rows) - -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 -(6 rows) - --- Compress twice to notice idempotent operation -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Compress again to verify errors are ignored -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- There should be no uncompressed chunks -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 -(6 rows) - -SELECT test.remote_exec(NULL, $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_1]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_2]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_3]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 4|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 3|f | 1|f - 3| 2|_timescaledb_internal|compress_hyper_2_3_chunk| |f | 0|f - 4| 2|_timescaledb_internal|compress_hyper_2_4_chunk| |f | 0|f -(4 rows) - - - remote_exec -------------- - -(1 row) - --- Decompress the chunks and replicas -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Should now be decompressed -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Decompress twice to generate NOTICE that the chunk is already decompressed -SELECT decompress_chunk(chunk, if_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; -NOTICE: chunk "_dist_hyper_1_1_chunk" is not compressed - decompress_chunk ------------------- - -(1 row) - -\x -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'compressed'; --[ RECORD 1 ]-------+-------------------------------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -owner | test_role_1 -num_dimensions | 2 -num_chunks | 3 -compression_enabled | t -is_distributed | t -replication_factor | 2 -data_nodes | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -tablespaces | - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; --[ RECORD 1 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_1_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_2} --[ RECORD 2 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_2_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_2,db_dist_compression_3} --[ RECORD 3 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_3_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_3} - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; --[ RECORD 1 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 1 -column_name | time -column_type | timestamp with time zone -dimension_type | Time -time_interval | @ 7 days -integer_interval | -integer_now_func | -num_partitions | --[ RECORD 2 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 2 -column_name | device -column_type | integer -dimension_type | Space -time_interval | -integer_interval | -integer_now_func | -num_partitions | 3 - -\x -SELECT * FROM chunks_detailed_size('compressed'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('compressed'::regclass) ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------------- - 16384 | 81920 | 0 | 98304 | db_dist_compression_1 - 16384 | 81920 | 0 | 98304 | db_dist_compression_2 - 16384 | 81920 | 0 | 98304 | db_dist_compression_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - --- Disable compression on distributed table tests -ALTER TABLE compressed SET (timescaledb.compress = false); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 0 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- -(0 rows) - ---Now re-enable compression -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT chunk_name, node_name, compression_status -FROM chunk_compression_stats('compressed') -ORDER BY 1, 2; - chunk_name | node_name | compression_status ------------------------+-----------------------+-------------------- - _dist_hyper_1_1_chunk | db_dist_compression_1 | Compressed - _dist_hyper_1_1_chunk | db_dist_compression_2 | Compressed - _dist_hyper_1_2_chunk | db_dist_compression_2 | Uncompressed - _dist_hyper_1_2_chunk | db_dist_compression_3 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_1 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_3 | Uncompressed -(6 rows) - --- ALTER TABLE on distributed compressed hypertable -ALTER TABLE compressed ADD COLUMN new_coli integer; -ALTER TABLE compressed ADD COLUMN new_colv varchar(30); -SELECT * FROM _timescaledb_catalog.hypertable_compression -ORDER BY attname; - hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst ----------------+----------+--------------------------+------------------------+----------------------+-------------+-------------------- - 1 | device | 0 | 1 | | | - 1 | new_coli | 4 | | | | - 1 | new_colv | 2 | | | | - 1 | temp | 3 | | | | - 1 | time | 4 | | 1 | f | t -(5 rows) - -SELECT count(*) from compressed where new_coli is not null; - count -------- - 0 -(1 row) - ---insert data into new chunk -INSERT INTO compressed -SELECT '2019-08-01 00:00', 100, 100, 1, 'newcolv' ; -SELECT count(compress_chunk(ch,true)) FROM show_chunks('compressed') ch; - count -------- - 4 -(1 row) - -SELECT * from compressed where new_coli is not null; - time | device | temp | new_coli | new_colv -------------------------------+--------+------+----------+---------- - Thu Aug 01 00:00:00 2019 PDT | 100 | 100 | 1 | newcolv -(1 row) - --- Test ALTER TABLE rename column on distributed hypertables -ALTER TABLE compressed RENAME new_coli TO new_intcol ; -ALTER TABLE compressed RENAME device TO device_id ; -SELECT * FROM test.remote_exec( NULL, - $$ SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname; $$ ); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_1]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_2]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_3]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- TEST insert data into compressed chunk -INSERT INTO compressed -SELECT '2019-08-01 01:00', 300, 300, 3, 'newcolv' ; -SELECT * from compressed where new_intcol = 3; - time | device_id | temp | new_intcol | new_colv -------------------------------+-----------+------+------------+---------- - Thu Aug 01 01:00:00 2019 PDT | 300 | 300 | 3 | newcolv -(1 row) - --- We're done with the table, so drop it. -DROP TABLE IF EXISTS compressed CASCADE; ------------------------------------------------------- --- Test compression policy on a distributed hypertable ------------------------------------------------------- -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - location2 char(10) NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL - ); -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => '31days'::interval, replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,conditions,t) -(1 row) - ---TEST 1-- ---cannot set policy without enabling compression -- -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression not enabled on hypertable "conditions" -\set ON_ERROR_STOP 1 --- TEST2 -- ---add a policy to compress chunks -- -alter table conditions set (timescaledb.compress, timescaledb.compress_segmentby = 'location', timescaledb.compress_orderby = 'time'); -insert into conditions -select generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '1 day'), 'POR', 'klick', 55, 75; -select add_compression_policy('conditions', '60d'::interval) AS compressjob_id -\gset -select * from _timescaledb_config.bgw_job where id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - -select * from alter_job(:compressjob_id, schedule_interval=>'1s'); - job_id | schedule_interval | max_runtime | max_retries | retry_period | scheduled | config | next_start | check_config | fixed_schedule | initial_start | timezone ---------+-------------------+-------------+-------------+--------------+-----------+-----------------------------------------------------+------------+-------------------------------------------------+----------------+---------------+---------- - 1000 | @ 1 sec | @ 0 | -1 | @ 1 hour | t | {"hypertable_id": 2, "compress_after": "@ 60 days"} | -infinity | _timescaledb_functions.policy_compression_check | f | | -(1 row) - -select * from _timescaledb_config.bgw_job where id >= 1000 ORDER BY id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 1 sec | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - --- we want only 1 chunk to be compressed -- -SELECT alter_job(id,config:=jsonb_set(config,'{maxchunks_to_compress}', '1')) -FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - alter_job ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - (1000,"@ 1 sec","@ 0",-1,"@ 1 hour",t,"{""hypertable_id"": 2, ""compress_after"": ""@ 60 days"", ""maxchunks_to_compress"": 1}",-infinity,_timescaledb_functions.policy_compression_check,f,,) -(1 row) - -insert into conditions -select now()::timestamp, 'TOK', 'sony', 55, 75; --- TEST3 -- ---only the old chunks will get compressed when policy is executed-- -CALL run_job(:compressjob_id); -select chunk_name, node_name, pg_size_pretty(before_compression_total_bytes) before_total, -pg_size_pretty( after_compression_total_bytes) after_total -from chunk_compression_stats('conditions') where compression_status like 'Compressed' order by chunk_name; - chunk_name | node_name | before_total | after_total ------------------------+-----------------------+--------------+------------- - _dist_hyper_2_6_chunk | db_dist_compression_1 | 32 kB | 40 kB - _dist_hyper_2_6_chunk | db_dist_compression_3 | 32 kB | 40 kB -(2 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 6 | 2 | _timescaledb_internal | _dist_hyper_2_6_chunk | | f | 1 | f - 7 | 2 | _timescaledb_internal | _dist_hyper_2_7_chunk | | f | 0 | f - 8 | 2 | _timescaledb_internal | _dist_hyper_2_8_chunk | | f | 0 | f -(3 rows) - --- TEST 4 -- ---cannot set another policy -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval, if_not_exists=>true); -NOTICE: compression policy already exists for hypertable "conditions", skipping - add_compression_policy ------------------------- - -1 -(1 row) - -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression policy already exists for hypertable or continuous aggregate "conditions" -select add_compression_policy('conditions', '30d'::interval, if_not_exists=>true); -WARNING: compression policy already exists for hypertable "conditions" - add_compression_policy ------------------------- - -1 -(1 row) - -\set ON_ERROR_STOP 1 ---TEST 5 -- --- drop the policy -- -select remove_compression_policy('conditions'); - remove_compression_policy ---------------------------- - t -(1 row) - -select count(*) from _timescaledb_config.bgw_job WHERE id>=1000; - count -------- - 0 -(1 row) - ---TEST 6 -- --- try to execute the policy after it has been dropped -- -\set ON_ERROR_STOP 0 -CALL run_job(:compressjob_id); -ERROR: job 1000 not found -\set ON_ERROR_STOP 1 --- We're done with the table, so drop it. -DROP TABLE IF EXISTS conditions CASCADE; ---TEST 7 ---compression policy for smallint, integer or bigint based partition hypertable ---smallint tests -CREATE TABLE test_table_smallint(time smallint, val int); -SELECT create_distributed_hypertable('test_table_smallint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ----------------------------------- - (3,public,test_table_smallint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT' -$$); -SELECT set_integer_now_func('test_table_smallint', 'dummy_now_smallint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_smallint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_smallint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_smallint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1001 | Compression Policy [1001] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 3 | {"hypertable_id": 3, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_smallint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_3_10_chunk | db_dist_compression_2 | 24576 | 24576 - _dist_hyper_3_10_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_3_9_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_3_9_chunk | db_dist_compression_2 | 24576 | 24576 -(4 rows) - ---integer tests -CREATE TABLE test_table_integer(time int, val int); -SELECT create_distributed_hypertable('test_table_integer', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ---------------------------------- - (4,public,test_table_integer,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER' -$$); -SELECT set_integer_now_func('test_table_integer', 'dummy_now_integer'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_integer SELECT generate_series(1,5), 10; -ALTER TABLE test_table_integer SET (timescaledb.compress); -SELECT add_compression_policy('test_table_integer', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 4 | {"hypertable_id": 4, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_integer') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_4_14_chunk | db_dist_compression_2 | 24576 | 24576 - _dist_hyper_4_14_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_4_15_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_4_15_chunk | db_dist_compression_3 | 24576 | 24576 -(4 rows) - ---bigint tests -CREATE TABLE test_table_bigint(time bigint, val int); -SELECT create_distributed_hypertable('test_table_bigint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable --------------------------------- - (5,public,test_table_bigint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT' -$$); -SELECT set_integer_now_func('test_table_bigint', 'dummy_now_bigint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_bigint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_bigint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_bigint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1003 | Compression Policy [1003] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 5 | {"hypertable_id": 5, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_bigint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_5_19_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_5_19_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_5_20_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_5_20_chunk | db_dist_compression_2 | 24576 | 24576 -(4 rows) - ---TEST8 insert into compressed chunks on dist. hypertable -CREATE TABLE test_recomp_int(time bigint, val int); -SELECT create_distributed_hypertable('test_recomp_int', 'time', chunk_time_interval => 20); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (6,public,test_recomp_int,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT' -$$); -select set_integer_now_func('test_recomp_int', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - -insert into test_recomp_int select generate_series(1,5), 10; -alter table test_recomp_int set (timescaledb.compress); -CREATE VIEW test_recomp_int_chunk_status as -SELECT - c.table_name as chunk_name, - c.status as chunk_status -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int'; ---compress chunks -SELECT compress_chunk(chunk) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - ---check the status -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - --- insert into compressed chunks of test_recomp_int (using same value for val)-- -insert into test_recomp_int select 10, 10; -SELECT count(*) from test_recomp_int where val = 10; - count -------- - 6 -(1 row) - ---chunk status should change --- -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - -SELECT -c.schema_name || '.' || c.table_name as "CHUNK_NAME" -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' \gset ---call recompress_chunk directly on distributed chunk -CALL recompress_chunk(:'CHUNK_NAME'::regclass); ---check chunk status now, should be compressed -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - -SELECT count(*) from test_recomp_int; - count -------- - 6 -(1 row) - ---add a policy-- -select add_compression_policy('test_recomp_int', 1::int) AS compressjob_id -\gset ---once again add data to the compressed chunk -insert into test_recomp_int select generate_series(5,7), 10; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - ---run the compression policy job, it will recompress chunks that are unordered -CALL run_job(:compressjob_id); -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - -RESET timescaledb.enable_per_data_node_queries; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - ----run copy tests ---copy data into existing chunk + for a new chunk -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT time_bucket(20, time ), count(*) -FROM test_recomp_int -GROUP BY time_bucket( 20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 12 - 100 | 3 -(2 rows) - ---another new chunk -INSERT INTO test_recomp_int VALUES( 65, 10); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 0 - _dist_hyper_6_26_chunk | 0 -(3 rows) - ---compress all 3 chunks --- ---check status, unordered chunk status will not change -SELECT compress_chunk(chunk, true) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk - _timescaledb_internal._dist_hyper_6_25_chunk - _timescaledb_internal._dist_hyper_6_26_chunk -(3 rows) - -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---interleave copy into 3 different chunks and check status-- -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 9 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - -RESET timescaledb.enable_per_data_node_queries; ---check compression_status afterwards-- -CALL recompress_all_chunks('test_recomp_int', 2, true); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -CALL run_job(:compressjob_id); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---verify that there are no errors if the policy/recompress_chunk is executed again ---on previously compressed chunks -CALL run_job(:compressjob_id); -CALL recompress_all_chunks('test_recomp_int', true); -NOTICE: nothing to recompress in chunk "_dist_hyper_6_24_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_25_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_26_chunk" ---decompress and recompress chunk -\set ON_ERROR_STOP 0 -SELECT decompress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - decompress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CALL recompress_all_chunks('test_recomp_int', 1, false); -ERROR: call compress_chunk instead of recompress_chunk -\set ON_ERROR_STOP 1 --- test alter column type with distributed hypertable -\set ON_ERROR_STOP 0 -ALTER TABLE test_table_smallint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_integer ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_bigint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -\set ON_ERROR_STOP 1 ---create a cont agg view on the ht with compressed chunks as well -SELECT compress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CREATE MATERIALIZED VIEW test_recomp_int_cont_view -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS SELECT time_bucket(BIGINT '5', "time"), SUM(val) - FROM test_recomp_int - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_recomp_int_cont_view', NULL, BIGINT '5', '1 day'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1005 -(1 row) - -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, NULL); -SELECT * FROM test_recomp_int ORDER BY 1; - time | val -------+----- - 1 | 10 - 2 | 10 - 3 | 10 - 4 | 10 - 5 | 10 - 5 | 10 - 6 | 10 - 7 | 10 - 10 | 10 - 11 | 11 - 12 | 12 - 13 | 13 - 14 | 14 - 15 | 15 - 65 | 10 - 66 | 66 - 70 | 70 - 100 | 100 - 101 | 100 - 102 | 100 - 103 | 100 - 104 | 100 -(22 rows) - -SELECT * FROM test_recomp_int_cont_view ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 - 5 | 40 - 10 | 60 - 15 | 15 - 65 | 76 - 70 | 70 - 100 | 500 -(7 rows) - ---TEST cagg triggers work on distributed hypertables when we insert into --- compressed chunks. -SELECT -CASE WHEN compress_chunk(chunk, true) IS NOT NULL THEN 'compress' END AS ch - FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk )q; - ch ----------- - compress - compress - compress -(3 rows) - -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 -(1 row) - ---insert into an existing compressed chunk and a new chunk -SET timescaledb.enable_distributed_insert_with_copy=false; -INSERT INTO test_recomp_int VALUES (1, 10), (2,10), (3, 10); -INSERT INTO test_recomp_int VALUES(51, 10); ---refresh the cagg and verify the new results -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 70 - 50 | 10 -(2 rows) - ---repeat test with copy setting turned to true -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO test_recomp_int VALUES (4, 10); -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 80 - 50 | 10 -(2 rows) - ---TEST drop one of the compressed chunks in test_recomp_int. The catalog ---tuple for the chunk will be preserved since we have a cagg. --- Verify that status is accurate. -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 9 | f | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - -SELECT drop_chunks('test_recomp_int', older_than=> 20::bigint ); - drop_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 0 | t | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - --- TEST drop should nuke everything -DROP TABLE test_recomp_int CASCADE; -NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to table _timescaledb_internal._hyper_7_27_chunk --- test compression default handling -CREATE TABLE test_defaults(time timestamptz NOT NULL, device_id int); -SELECT create_distributed_hypertable('test_defaults','time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (8,public,test_defaults,t) -(1 row) - -ALTER TABLE test_defaults SET (timescaledb.compress,timescaledb.compress_segmentby='device_id'); --- create 2 chunks -INSERT INTO test_defaults SELECT '2000-01-01', 1; -INSERT INTO test_defaults SELECT '2001-01-01', 1; --- compress first chunk -SELECT compress_chunk(show_chunks) AS compressed_chunk FROM show_chunks('test_defaults') ORDER BY show_chunks::text LIMIT 1; - compressed_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_8_29_chunk -(1 row) - -SELECT * FROM test_defaults ORDER BY 1; - time | device_id -------------------------------+----------- - Sat Jan 01 00:00:00 2000 PST | 1 - Mon Jan 01 00:00:00 2001 PST | 1 -(2 rows) - -ALTER TABLE test_defaults ADD COLUMN c1 int; -ALTER TABLE test_defaults ADD COLUMN c2 int NOT NULL DEFAULT 42; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(2 rows) - --- try insert into compressed and recompress -INSERT INTO test_defaults SELECT '2000-01-01', 2; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - -CALL recompress_all_chunks('test_defaults', 1, false); -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - --- test dropping columns from compressed -CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); -SELECT create_distributed_hypertable('test_drop','time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (9,public,test_drop,t) -(1 row) - -ALTER TABLE test_drop SET (timescaledb.compress,timescaledb.compress_segmentby='device',timescaledb.compress_orderby='o1,o2'); --- switch to WARNING only to suppress compress_chunk NOTICEs -SET client_min_messages TO WARNING; --- create some chunks each with different physical layout -ALTER TABLE test_drop DROP COLUMN f1; -INSERT INTO test_drop SELECT NULL,NULL,'2000-01-01',1,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 1 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f2; --- test non-existant column -\set ON_ERROR_STOP 0 -ALTER TABLE test_drop DROP COLUMN f10; -ERROR: column "f10" of relation "test_drop" does not exist -\set ON_ERROR_STOP 1 -ALTER TABLE test_drop DROP COLUMN IF EXISTS f10; -INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 2 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f3; -INSERT INTO test_drop SELECT '2003-01-01',3,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 3 -(1 row) - -ALTER TABLE test_drop ADD COLUMN c1 TEXT; -ALTER TABLE test_drop ADD COLUMN c2 TEXT; -INSERT INTO test_drop SELECT '2004-01-01',4,'o1','o2','c1','c2-4'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 4 -(1 row) - -ALTER TABLE test_drop DROP COLUMN c1; -INSERT INTO test_drop SELECT '2005-01-01',5,'o1','o2','c2-5'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 5 -(1 row) - -RESET client_min_messages; -SELECT * FROM test_drop ORDER BY 1; - time | device | o1 | o2 | c2 -------------------------------+--------+----+----+------ - Sat Jan 01 00:00:00 2000 PST | 1 | o1 | o2 | - Mon Jan 01 00:00:00 2001 PST | 2 | o1 | o2 | - Wed Jan 01 00:00:00 2003 PST | 3 | o1 | o2 | - Thu Jan 01 00:00:00 2004 PST | 4 | o1 | o2 | c2-4 - Sat Jan 01 00:00:00 2005 PST | 5 | o1 | o2 | c2-5 -(5 rows) - --- check dropped columns got removed from catalog --- only c2 should be left in metadata -SELECT attname -FROM _timescaledb_catalog.hypertable_compression htc -INNER JOIN _timescaledb_catalog.hypertable ht - ON ht.id=htc.hypertable_id AND ht.table_name='test_drop' -WHERE attname NOT IN ('time','device','o1','o2') -ORDER BY 1; - attname ---------- - c2 -(1 row) - --- test ADD COLUMN IF NOT EXISTS on a distributed hypertable -CREATE TABLE metric (time TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL); -SELECT create_distributed_hypertable('metric', 'time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (10,public,metric,t) -(1 row) - -ALTER TABLE metric SET ( -timescaledb.compress, -timescaledb.compress_segmentby = 'dev_id', -timescaledb.compress_orderby = 'time DESC' -); -INSERT INTO metric(time, val, dev_id) -SELECT s.*, 3.14+1, 1 -FROM generate_series('2021-07-01 00:00:00'::timestamp, - '2021-08-17 00:02:00'::timestamp, '30 s'::interval) s; -SELECT compress_chunk(chunk) -FROM show_chunks('metric') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_36_chunk - _timescaledb_internal._dist_hyper_10_37_chunk - _timescaledb_internal._dist_hyper_10_38_chunk - _timescaledb_internal._dist_hyper_10_39_chunk - _timescaledb_internal._dist_hyper_10_40_chunk - _timescaledb_internal._dist_hyper_10_41_chunk - _timescaledb_internal._dist_hyper_10_42_chunk -(7 rows) - --- make sure we have chunks on all data nodes -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks where hypertable_name like 'metric'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-------------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+------------------------- - public | metric | _timescaledb_internal | _dist_hyper_10_36_chunk | time | timestamp with time zone | Wed Jun 30 17:00:00 2021 PDT | Wed Jul 07 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_37_chunk | time | timestamp with time zone | Wed Jul 07 17:00:00 2021 PDT | Wed Jul 14 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_38_chunk | time | timestamp with time zone | Wed Jul 14 17:00:00 2021 PDT | Wed Jul 21 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_39_chunk | time | timestamp with time zone | Wed Jul 21 17:00:00 2021 PDT | Wed Jul 28 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_40_chunk | time | timestamp with time zone | Wed Jul 28 17:00:00 2021 PDT | Wed Aug 04 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_41_chunk | time | timestamp with time zone | Wed Aug 04 17:00:00 2021 PDT | Wed Aug 11 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_42_chunk | time | timestamp with time zone | Wed Aug 11 17:00:00 2021 PDT | Wed Aug 18 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} -(7 rows) - --- perform all combinations --- [IF NOT EXISTS] - [] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; --- [IF NOT EXISTS] - ["medium"] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; -NOTICE: column "medium" of relation "metric" already exists, skipping --- [] - [] -ALTER TABLE metric ADD COLUMN "medium_1" varchar; --- [] - ["medium_1"] -\set ON_ERROR_STOP 0 -ALTER TABLE metric ADD COLUMN "medium_1" varchar; -ERROR: column "medium_1" of relation "metric" already exists -SELECT * FROM metric limit 5; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+--------+---------- - Wed Jul 21 16:59:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:59:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:57:30 2021 PDT | 4.14 | 1 | | -(5 rows) - -SELECT * FROM metric where medium is not null; - time | val | dev_id | medium | medium_1 -------+-----+--------+--------+---------- -(0 rows) - --- INSERTs operate normally on the added column -INSERT INTO metric (time, val, dev_id, medium) -SELECT s.*, 3.14+1, 1, 'medium_value_text' -FROM generate_series('2021-08-18 00:00:00'::timestamp, - '2021-08-19 00:02:00'::timestamp, '30 s'::interval) s; -SELECT * FROM metric where medium is not null ORDER BY time LIMIT 1; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+-------------------+---------- - Wed Aug 18 00:00:00 2021 PDT | 4.14 | 1 | medium_value_text | -(1 row) - --- test alter_data_node(unvailable) with compressed chunks --- --- create compressed distributed hypertable -CREATE TABLE compressed(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (11,public,compressed,t) -(1 row) - --- insert data and get chunks distribution -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+--------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT count(*) FROM compressed; - count -------- - 49 -(1 row) - --- make data node unavailable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 5 chunks - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55433,db_dist_compression_1,f) -(1 row) - -SET ROLE :ROLE_1; --- update compressed chunks -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; --- ensure that chunks associated with unavailable data node 1 --- are removed after being updated -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+----------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2', :'DATA_NODE_3'], $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- make data node available again -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,f) -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,t) -(1 row) - -SET ROLE :ROLE_1; --- ensure that stale chunks being dropped from data node 1 automatically -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- recompress chunks -CALL recompress_all_chunks('compressed', 3, true); -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE compressed; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_compression-15.out b/tsl/test/expected/dist_compression-15.out deleted file mode 100644 index 56b481eba7c..00000000000 --- a/tsl/test/expected/dist_compression-15.out +++ /dev/null @@ -1,1776 +0,0 @@ --- 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. ---------------------------------------------------- --- Test compression on a distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -\ir include/compression_utils.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 ECHO errors -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_compression_1 | db_dist_compression_1 | t | t | t - db_dist_compression_2 | db_dist_compression_2 | t | t | t - db_dist_compression_3 | db_dist_compression_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE compressed(time timestamptz, device int, temp float); --- Replicate twice to see that compress_chunk compresses all replica chunks -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (1,public,compressed,t) -(1 row) - -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -\x -SELECT * FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; --[ RECORD 1 ]------------+------------------------- -id | 1 -schema_name | public -table_name | compressed -associated_schema_name | _timescaledb_internal -associated_table_prefix | _dist_hyper_1 -num_dimensions | 2 -chunk_sizing_func_schema | _timescaledb_functions -chunk_sizing_func_name | calculate_chunk_interval -chunk_target_size | 0 -compression_state | 1 -compressed_hypertable_id | -replication_factor | 2 -status | 0 - -\x -SELECT test.remote_exec(NULL, $$ -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_1]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_2]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_2]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - -NOTICE: [db_dist_compression_3]: -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed' -NOTICE: [db_dist_compression_3]: -table_name|compressed_hypertable_id -----------+------------------------ -compressed| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - --- There should be no compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Test that compression is rolled back on aborted transaction -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Data nodes should now report compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Abort the transaction -ROLLBACK; --- No compressed chunks since we rolled back -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Compress for real this time -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Check that one chunk, and its replica, is compressed -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - -select * from hypertable_compression_stats('compressed'); - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - 2 | 1 | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - 2 | 0 | | | | | | | | | db_dist_compression_3 - 2 | 1 | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 -(3 rows) - ---- Decompress the chunk and replica -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - --- Compress odd numbered chunks -SELECT compress_chunk(chunk) FROM -( - SELECT *, row_number() OVER () AS rownum - FROM show_chunks('compressed') AS chunk - ORDER BY chunk -) AS t -WHERE rownum % 2 = 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(2 rows) - -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 -(6 rows) - --- Compress twice to notice idempotent operation -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Compress again to verify errors are ignored -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- There should be no uncompressed chunks -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 | db_dist_compression_3 -(6 rows) - -SELECT test.remote_exec(NULL, $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_1]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_2]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk | 5|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 6|f | 1|f - 5| 2|_timescaledb_internal|compress_hyper_2_5_chunk| |f | 0|f - 6| 2|_timescaledb_internal|compress_hyper_2_6_chunk| |f | 0|f -(4 rows) - - -NOTICE: [db_dist_compression_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id -NOTICE: [db_dist_compression_3]: -id|hypertable_id|schema_name |table_name |compressed_chunk_id|dropped|status|osm_chunk ---+-------------+---------------------+------------------------+-------------------+-------+------+--------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk | 4|f | 1|f - 2| 1|_timescaledb_internal|_dist_hyper_1_3_chunk | 3|f | 1|f - 3| 2|_timescaledb_internal|compress_hyper_2_3_chunk| |f | 0|f - 4| 2|_timescaledb_internal|compress_hyper_2_4_chunk| |f | 0|f -(4 rows) - - - remote_exec -------------- - -(1 row) - --- Decompress the chunks and replicas -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - decompress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk -(3 rows) - --- Should now be decompressed -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | Uncompressed | | | | | | | | | db_dist_compression_3 -(6 rows) - --- Decompress twice to generate NOTICE that the chunk is already decompressed -SELECT decompress_chunk(chunk, if_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; -NOTICE: chunk "_dist_hyper_1_1_chunk" is not compressed - decompress_chunk ------------------- - -(1 row) - -\x -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'compressed'; --[ RECORD 1 ]-------+-------------------------------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -owner | test_role_1 -num_dimensions | 2 -num_chunks | 3 -compression_enabled | t -is_distributed | t -replication_factor | 2 -data_nodes | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -tablespaces | - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; --[ RECORD 1 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_1_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_2} --[ RECORD 2 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_2_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_2,db_dist_compression_3} --[ RECORD 3 ]----------+---------------------------------------------- -hypertable_schema | public -hypertable_name | compressed -chunk_schema | _timescaledb_internal -chunk_name | _dist_hyper_1_3_chunk -primary_dimension | time -primary_dimension_type | timestamp with time zone -range_start | Wed Feb 28 16:00:00 2018 PST -range_end | Wed Mar 07 16:00:00 2018 PST -range_start_integer | -range_end_integer | -is_compressed | f -chunk_tablespace | -data_nodes | {db_dist_compression_1,db_dist_compression_3} - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; --[ RECORD 1 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 1 -column_name | time -column_type | timestamp with time zone -dimension_type | Time -time_interval | @ 7 days -integer_interval | -integer_now_func | -num_partitions | --[ RECORD 2 ]-----+------------------------- -hypertable_schema | public -hypertable_name | compressed -dimension_number | 2 -column_name | device -column_type | integer -dimension_type | Space -time_interval | -integer_interval | -integer_now_func | -num_partitions | 3 - -\x -SELECT * FROM chunks_detailed_size('compressed'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_compression_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('compressed'::regclass) ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------------- - 16384 | 81920 | 0 | 98304 | db_dist_compression_1 - 16384 | 81920 | 0 | 98304 | db_dist_compression_2 - 16384 | 81920 | 0 | 98304 | db_dist_compression_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - --- Disable compression on distributed table tests -ALTER TABLE compressed SET (timescaledb.compress = false); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 0 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- -(0 rows) - ---Now re-enable compression -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - table_name | compression_state | compressed_hypertable_id -------------+-------------------+-------------------------- - compressed | 1 | -(1 row) - -SELECT * FROM timescaledb_information.compression_settings order by attname; - hypertable_schema | hypertable_name | attname | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst --------------------+-----------------+---------+------------------------+----------------------+-------------+-------------------- - public | compressed | device | 1 | | | - public | compressed | time | | 1 | f | t -(2 rows) - -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT chunk_name, node_name, compression_status -FROM chunk_compression_stats('compressed') -ORDER BY 1, 2; - chunk_name | node_name | compression_status ------------------------+-----------------------+-------------------- - _dist_hyper_1_1_chunk | db_dist_compression_1 | Compressed - _dist_hyper_1_1_chunk | db_dist_compression_2 | Compressed - _dist_hyper_1_2_chunk | db_dist_compression_2 | Uncompressed - _dist_hyper_1_2_chunk | db_dist_compression_3 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_1 | Uncompressed - _dist_hyper_1_3_chunk | db_dist_compression_3 | Uncompressed -(6 rows) - --- ALTER TABLE on distributed compressed hypertable -ALTER TABLE compressed ADD COLUMN new_coli integer; -ALTER TABLE compressed ADD COLUMN new_colv varchar(30); -SELECT * FROM _timescaledb_catalog.hypertable_compression -ORDER BY attname; - hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst ----------------+----------+--------------------------+------------------------+----------------------+-------------+-------------------- - 1 | device | 0 | 1 | | | - 1 | new_coli | 4 | | | | - 1 | new_colv | 2 | | | | - 1 | temp | 3 | | | | - 1 | time | 4 | | 1 | f | t -(5 rows) - -SELECT count(*) from compressed where new_coli is not null; - count -------- - 0 -(1 row) - ---insert data into new chunk -INSERT INTO compressed -SELECT '2019-08-01 00:00', 100, 100, 1, 'newcolv' ; -SELECT count(compress_chunk(ch,true)) FROM show_chunks('compressed') ch; - count -------- - 4 -(1 row) - -SELECT * from compressed where new_coli is not null; - time | device | temp | new_coli | new_colv -------------------------------+--------+------+----------+---------- - Thu Aug 01 00:00:00 2019 PDT | 100 | 100 | 1 | newcolv -(1 row) - --- Test ALTER TABLE rename column on distributed hypertables -ALTER TABLE compressed RENAME new_coli TO new_intcol ; -ALTER TABLE compressed RENAME device TO device_id ; -SELECT * FROM test.remote_exec( NULL, - $$ SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname; $$ ); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_1]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_2]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname -NOTICE: [db_dist_compression_3]: -hypertable_id|attname |compression_algorithm_id|segmentby_column_index|orderby_column_index|orderby_asc|orderby_nullsfirst --------------+----------+------------------------+----------------------+--------------------+-----------+------------------ - 1|device_id | 0| 1| | | - 1|new_intcol| 4| | | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- TEST insert data into compressed chunk -INSERT INTO compressed -SELECT '2019-08-01 01:00', 300, 300, 3, 'newcolv' ; -SELECT * from compressed where new_intcol = 3; - time | device_id | temp | new_intcol | new_colv -------------------------------+-----------+------+------------+---------- - Thu Aug 01 01:00:00 2019 PDT | 300 | 300 | 3 | newcolv -(1 row) - --- We're done with the table, so drop it. -DROP TABLE IF EXISTS compressed CASCADE; ------------------------------------------------------- --- Test compression policy on a distributed hypertable ------------------------------------------------------- -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - location2 char(10) NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL - ); -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => '31days'::interval, replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,conditions,t) -(1 row) - ---TEST 1-- ---cannot set policy without enabling compression -- -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression not enabled on hypertable "conditions" -\set ON_ERROR_STOP 1 --- TEST2 -- ---add a policy to compress chunks -- -alter table conditions set (timescaledb.compress, timescaledb.compress_segmentby = 'location', timescaledb.compress_orderby = 'time'); -insert into conditions -select generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '1 day'), 'POR', 'klick', 55, 75; -select add_compression_policy('conditions', '60d'::interval) AS compressjob_id -\gset -select * from _timescaledb_config.bgw_job where id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 12 hours | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - -select * from alter_job(:compressjob_id, schedule_interval=>'1s'); - job_id | schedule_interval | max_runtime | max_retries | retry_period | scheduled | config | next_start | check_config | fixed_schedule | initial_start | timezone ---------+-------------------+-------------+-------------+--------------+-----------+-----------------------------------------------------+------------+-------------------------------------------------+----------------+---------------+---------- - 1000 | @ 1 sec | @ 0 | -1 | @ 1 hour | t | {"hypertable_id": 2, "compress_after": "@ 60 days"} | -infinity | _timescaledb_functions.policy_compression_check | f | | -(1 row) - -select * from _timescaledb_config.bgw_job where id >= 1000 ORDER BY id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-----------------------------------------------------+------------------------+--------------------------+---------- - 1000 | Compression Policy [1000] | @ 1 sec | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 2 | {"hypertable_id": 2, "compress_after": "@ 60 days"} | _timescaledb_functions | policy_compression_check | -(1 row) - --- we want only 1 chunk to be compressed -- -SELECT alter_job(id,config:=jsonb_set(config,'{maxchunks_to_compress}', '1')) -FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - alter_job ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - (1000,"@ 1 sec","@ 0",-1,"@ 1 hour",t,"{""hypertable_id"": 2, ""compress_after"": ""@ 60 days"", ""maxchunks_to_compress"": 1}",-infinity,_timescaledb_functions.policy_compression_check,f,,) -(1 row) - -insert into conditions -select now()::timestamp, 'TOK', 'sony', 55, 75; --- TEST3 -- ---only the old chunks will get compressed when policy is executed-- -CALL run_job(:compressjob_id); -select chunk_name, node_name, pg_size_pretty(before_compression_total_bytes) before_total, -pg_size_pretty( after_compression_total_bytes) after_total -from chunk_compression_stats('conditions') where compression_status like 'Compressed' order by chunk_name; - chunk_name | node_name | before_total | after_total ------------------------+-----------------------+--------------+------------- - _dist_hyper_2_6_chunk | db_dist_compression_1 | 32 kB | 40 kB - _dist_hyper_2_6_chunk | db_dist_compression_3 | 32 kB | 40 kB -(2 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+-----------------------+---------------------+---------+--------+----------- - 6 | 2 | _timescaledb_internal | _dist_hyper_2_6_chunk | | f | 1 | f - 7 | 2 | _timescaledb_internal | _dist_hyper_2_7_chunk | | f | 0 | f - 8 | 2 | _timescaledb_internal | _dist_hyper_2_8_chunk | | f | 0 | f -(3 rows) - --- TEST 4 -- ---cannot set another policy -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval, if_not_exists=>true); -NOTICE: compression policy already exists for hypertable "conditions", skipping - add_compression_policy ------------------------- - -1 -(1 row) - -select add_compression_policy('conditions', '60d'::interval); -ERROR: compression policy already exists for hypertable or continuous aggregate "conditions" -select add_compression_policy('conditions', '30d'::interval, if_not_exists=>true); -WARNING: compression policy already exists for hypertable "conditions" - add_compression_policy ------------------------- - -1 -(1 row) - -\set ON_ERROR_STOP 1 ---TEST 5 -- --- drop the policy -- -select remove_compression_policy('conditions'); - remove_compression_policy ---------------------------- - t -(1 row) - -select count(*) from _timescaledb_config.bgw_job WHERE id>=1000; - count -------- - 0 -(1 row) - ---TEST 6 -- --- try to execute the policy after it has been dropped -- -\set ON_ERROR_STOP 0 -CALL run_job(:compressjob_id); -ERROR: job 1000 not found -\set ON_ERROR_STOP 1 --- We're done with the table, so drop it. -DROP TABLE IF EXISTS conditions CASCADE; ---TEST 7 ---compression policy for smallint, integer or bigint based partition hypertable ---smallint tests -CREATE TABLE test_table_smallint(time smallint, val int); -SELECT create_distributed_hypertable('test_table_smallint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ----------------------------------- - (3,public,test_table_smallint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT' -$$); -SELECT set_integer_now_func('test_table_smallint', 'dummy_now_smallint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_smallint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_smallint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_smallint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1001 | Compression Policy [1001] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 3 | {"hypertable_id": 3, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_smallint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_3_10_chunk | db_dist_compression_2 | 24576 | 24576 - _dist_hyper_3_10_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_3_9_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_3_9_chunk | db_dist_compression_2 | 24576 | 24576 -(4 rows) - ---integer tests -CREATE TABLE test_table_integer(time int, val int); -SELECT create_distributed_hypertable('test_table_integer', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable ---------------------------------- - (4,public,test_table_integer,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER' -$$); -SELECT set_integer_now_func('test_table_integer', 'dummy_now_integer'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_integer SELECT generate_series(1,5), 10; -ALTER TABLE test_table_integer SET (timescaledb.compress); -SELECT add_compression_policy('test_table_integer', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1002 | Compression Policy [1002] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 4 | {"hypertable_id": 4, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_integer') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_4_14_chunk | db_dist_compression_2 | 24576 | 24576 - _dist_hyper_4_14_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_4_15_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_4_15_chunk | db_dist_compression_3 | 24576 | 24576 -(4 rows) - ---bigint tests -CREATE TABLE test_table_bigint(time bigint, val int); -SELECT create_distributed_hypertable('test_table_bigint', 'time', chunk_time_interval => 1, replication_factor => 2); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable --------------------------------- - (5,public,test_table_bigint,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT' -$$); -SELECT set_integer_now_func('test_table_bigint', 'dummy_now_bigint'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO test_table_bigint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_bigint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_bigint', 2::int) AS compressjob_id \gset -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - id | application_name | schedule_interval | max_runtime | max_retries | retry_period | proc_schema | proc_name | owner | scheduled | fixed_schedule | initial_start | hypertable_id | config | check_schema | check_name | timezone -------+---------------------------+-------------------+-------------+-------------+--------------+------------------------+--------------------+-------------+-----------+----------------+---------------+---------------+-------------------------------------------+------------------------+--------------------------+---------- - 1003 | Compression Policy [1003] | @ 1 day | @ 0 | -1 | @ 1 hour | _timescaledb_functions | policy_compression | test_role_1 | t | f | | 5 | {"hypertable_id": 5, "compress_after": 2} | _timescaledb_functions | policy_compression_check | -(1 row) - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_bigint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - chunk_name | node_name | before_compression_total_bytes | after_compression_total_bytes -------------------------+-----------------------+--------------------------------+------------------------------- - _dist_hyper_5_19_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_5_19_chunk | db_dist_compression_3 | 24576 | 24576 - _dist_hyper_5_20_chunk | db_dist_compression_1 | 24576 | 24576 - _dist_hyper_5_20_chunk | db_dist_compression_2 | 24576 | 24576 -(4 rows) - ---TEST8 insert into compressed chunks on dist. hypertable -CREATE TABLE test_recomp_int(time bigint, val int); -SELECT create_distributed_hypertable('test_recomp_int', 'time', chunk_time_interval => 20); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (6,public,test_recomp_int,t) -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT' -$$); -select set_integer_now_func('test_recomp_int', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - -insert into test_recomp_int select generate_series(1,5), 10; -alter table test_recomp_int set (timescaledb.compress); -CREATE VIEW test_recomp_int_chunk_status as -SELECT - c.table_name as chunk_name, - c.status as chunk_status -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int'; ---compress chunks -SELECT compress_chunk(chunk) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - ---check the status -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - --- insert into compressed chunks of test_recomp_int (using same value for val)-- -insert into test_recomp_int select 10, 10; -SELECT count(*) from test_recomp_int where val = 10; - count -------- - 6 -(1 row) - ---chunk status should change --- -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - -SELECT -c.schema_name || '.' || c.table_name as "CHUNK_NAME" -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' \gset ---call recompress_chunk directly on distributed chunk -CALL recompress_chunk(:'CHUNK_NAME'::regclass); ---check chunk status now, should be compressed -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - -SELECT count(*) from test_recomp_int; - count -------- - 6 -(1 row) - ---add a policy-- -select add_compression_policy('test_recomp_int', 1::int) AS compressjob_id -\gset ---once again add data to the compressed chunk -insert into test_recomp_int select generate_series(5,7), 10; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 -(1 row) - ---run the compression policy job, it will recompress chunks that are unordered -CALL run_job(:compressjob_id); -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT count(*) from test_recomp_int; - count -------- - 9 -(1 row) - -RESET timescaledb.enable_per_data_node_queries; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 -(1 row) - ----run copy tests ---copy data into existing chunk + for a new chunk -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT time_bucket(20, time ), count(*) -FROM test_recomp_int -GROUP BY time_bucket( 20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 12 - 100 | 3 -(2 rows) - ---another new chunk -INSERT INTO test_recomp_int VALUES( 65, 10); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 0 - _dist_hyper_6_26_chunk | 0 -(3 rows) - ---compress all 3 chunks --- ---check status, unordered chunk status will not change -SELECT compress_chunk(chunk, true) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk - _timescaledb_internal._dist_hyper_6_25_chunk - _timescaledb_internal._dist_hyper_6_26_chunk -(3 rows) - -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---interleave copy into 3 different chunks and check status-- -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 9 - _dist_hyper_6_25_chunk | 9 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - time_bucket | count --------------+------- - 0 | 14 - 60 | 3 - 100 | 5 -(3 rows) - -RESET timescaledb.enable_per_data_node_queries; ---check compression_status afterwards-- -CALL recompress_all_chunks('test_recomp_int', 2, true); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 9 -(3 rows) - -CALL run_job(:compressjob_id); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - chunk_name | chunk_status -------------------------+-------------- - _dist_hyper_6_24_chunk | 1 - _dist_hyper_6_25_chunk | 1 - _dist_hyper_6_26_chunk | 1 -(3 rows) - ---verify that there are no errors if the policy/recompress_chunk is executed again ---on previously compressed chunks -CALL run_job(:compressjob_id); -CALL recompress_all_chunks('test_recomp_int', true); -NOTICE: nothing to recompress in chunk "_dist_hyper_6_24_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_25_chunk" -NOTICE: nothing to recompress in chunk "_dist_hyper_6_26_chunk" ---decompress and recompress chunk -\set ON_ERROR_STOP 0 -SELECT decompress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - decompress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CALL recompress_all_chunks('test_recomp_int', 1, false); -ERROR: call compress_chunk instead of recompress_chunk -\set ON_ERROR_STOP 1 --- test alter column type with distributed hypertable -\set ON_ERROR_STOP 0 -ALTER TABLE test_table_smallint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_integer ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -ALTER TABLE test_table_bigint ALTER COLUMN val TYPE float; -ERROR: operation not supported on hypertables that have compression enabled -\set ON_ERROR_STOP 1 ---create a cont agg view on the ht with compressed chunks as well -SELECT compress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -CREATE MATERIALIZED VIEW test_recomp_int_cont_view -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS SELECT time_bucket(BIGINT '5', "time"), SUM(val) - FROM test_recomp_int - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_recomp_int_cont_view', NULL, BIGINT '5', '1 day'::interval); - add_continuous_aggregate_policy ---------------------------------- - 1005 -(1 row) - -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, NULL); -SELECT * FROM test_recomp_int ORDER BY 1; - time | val -------+----- - 1 | 10 - 2 | 10 - 3 | 10 - 4 | 10 - 5 | 10 - 5 | 10 - 6 | 10 - 7 | 10 - 10 | 10 - 11 | 11 - 12 | 12 - 13 | 13 - 14 | 14 - 15 | 15 - 65 | 10 - 66 | 66 - 70 | 70 - 100 | 100 - 101 | 100 - 102 | 100 - 103 | 100 - 104 | 100 -(22 rows) - -SELECT * FROM test_recomp_int_cont_view ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 - 5 | 40 - 10 | 60 - 15 | 15 - 65 | 76 - 70 | 70 - 100 | 500 -(7 rows) - ---TEST cagg triggers work on distributed hypertables when we insert into --- compressed chunks. -SELECT -CASE WHEN compress_chunk(chunk, true) IS NOT NULL THEN 'compress' END AS ch - FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk )q; - ch ----------- - compress - compress - compress -(3 rows) - -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 40 -(1 row) - ---insert into an existing compressed chunk and a new chunk -SET timescaledb.enable_distributed_insert_with_copy=false; -INSERT INTO test_recomp_int VALUES (1, 10), (2,10), (3, 10); -INSERT INTO test_recomp_int VALUES(51, 10); ---refresh the cagg and verify the new results -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 70 - 50 | 10 -(2 rows) - ---repeat test with copy setting turned to true -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO test_recomp_int VALUES (4, 10); -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - time_bucket | sum --------------+----- - 0 | 80 - 50 | 10 -(2 rows) - ---TEST drop one of the compressed chunks in test_recomp_int. The catalog ---tuple for the chunk will be preserved since we have a cagg. --- Verify that status is accurate. -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 9 | f | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - -SELECT drop_chunks('test_recomp_int', older_than=> 20::bigint ); - drop_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_6_24_chunk -(1 row) - -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - chunk_name | chunk_status | dropped | comp_id -------------------------+--------------+---------+--------- - _dist_hyper_6_24_chunk | 0 | t | - _dist_hyper_6_25_chunk | 1 | f | - _dist_hyper_6_26_chunk | 1 | f | - _dist_hyper_6_28_chunk | 0 | f | -(4 rows) - --- TEST drop should nuke everything -DROP TABLE test_recomp_int CASCADE; -NOTICE: drop cascades to 2 other objects -NOTICE: drop cascades to table _timescaledb_internal._hyper_7_27_chunk --- test compression default handling -CREATE TABLE test_defaults(time timestamptz NOT NULL, device_id int); -SELECT create_distributed_hypertable('test_defaults','time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (8,public,test_defaults,t) -(1 row) - -ALTER TABLE test_defaults SET (timescaledb.compress,timescaledb.compress_segmentby='device_id'); --- create 2 chunks -INSERT INTO test_defaults SELECT '2000-01-01', 1; -INSERT INTO test_defaults SELECT '2001-01-01', 1; --- compress first chunk -SELECT compress_chunk(show_chunks) AS compressed_chunk FROM show_chunks('test_defaults') ORDER BY show_chunks::text LIMIT 1; - compressed_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_8_29_chunk -(1 row) - -SELECT * FROM test_defaults ORDER BY 1; - time | device_id -------------------------------+----------- - Sat Jan 01 00:00:00 2000 PST | 1 - Mon Jan 01 00:00:00 2001 PST | 1 -(2 rows) - -ALTER TABLE test_defaults ADD COLUMN c1 int; -ALTER TABLE test_defaults ADD COLUMN c2 int NOT NULL DEFAULT 42; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(2 rows) - --- try insert into compressed and recompress -INSERT INTO test_defaults SELECT '2000-01-01', 2; -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - -CALL recompress_all_chunks('test_defaults', 1, false); -SELECT * FROM test_defaults ORDER BY 1,2; - time | device_id | c1 | c2 -------------------------------+-----------+----+---- - Sat Jan 01 00:00:00 2000 PST | 1 | | 42 - Sat Jan 01 00:00:00 2000 PST | 2 | | 42 - Mon Jan 01 00:00:00 2001 PST | 1 | | 42 -(3 rows) - --- test dropping columns from compressed -CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); -SELECT create_distributed_hypertable('test_drop','time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (9,public,test_drop,t) -(1 row) - -ALTER TABLE test_drop SET (timescaledb.compress,timescaledb.compress_segmentby='device',timescaledb.compress_orderby='o1,o2'); --- switch to WARNING only to suppress compress_chunk NOTICEs -SET client_min_messages TO WARNING; --- create some chunks each with different physical layout -ALTER TABLE test_drop DROP COLUMN f1; -INSERT INTO test_drop SELECT NULL,NULL,'2000-01-01',1,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 1 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f2; --- test non-existant column -\set ON_ERROR_STOP 0 -ALTER TABLE test_drop DROP COLUMN f10; -ERROR: column "f10" of relation "test_drop" does not exist -\set ON_ERROR_STOP 1 -ALTER TABLE test_drop DROP COLUMN IF EXISTS f10; -INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 2 -(1 row) - -ALTER TABLE test_drop DROP COLUMN f3; -INSERT INTO test_drop SELECT '2003-01-01',3,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 3 -(1 row) - -ALTER TABLE test_drop ADD COLUMN c1 TEXT; -ALTER TABLE test_drop ADD COLUMN c2 TEXT; -INSERT INTO test_drop SELECT '2004-01-01',4,'o1','o2','c1','c2-4'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 4 -(1 row) - -ALTER TABLE test_drop DROP COLUMN c1; -INSERT INTO test_drop SELECT '2005-01-01',5,'o1','o2','c2-5'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - count -------- - 5 -(1 row) - -RESET client_min_messages; -SELECT * FROM test_drop ORDER BY 1; - time | device | o1 | o2 | c2 -------------------------------+--------+----+----+------ - Sat Jan 01 00:00:00 2000 PST | 1 | o1 | o2 | - Mon Jan 01 00:00:00 2001 PST | 2 | o1 | o2 | - Wed Jan 01 00:00:00 2003 PST | 3 | o1 | o2 | - Thu Jan 01 00:00:00 2004 PST | 4 | o1 | o2 | c2-4 - Sat Jan 01 00:00:00 2005 PST | 5 | o1 | o2 | c2-5 -(5 rows) - --- check dropped columns got removed from catalog --- only c2 should be left in metadata -SELECT attname -FROM _timescaledb_catalog.hypertable_compression htc -INNER JOIN _timescaledb_catalog.hypertable ht - ON ht.id=htc.hypertable_id AND ht.table_name='test_drop' -WHERE attname NOT IN ('time','device','o1','o2') -ORDER BY 1; - attname ---------- - c2 -(1 row) - --- test ADD COLUMN IF NOT EXISTS on a distributed hypertable -CREATE TABLE metric (time TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL); -SELECT create_distributed_hypertable('metric', 'time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (10,public,metric,t) -(1 row) - -ALTER TABLE metric SET ( -timescaledb.compress, -timescaledb.compress_segmentby = 'dev_id', -timescaledb.compress_orderby = 'time DESC' -); -INSERT INTO metric(time, val, dev_id) -SELECT s.*, 3.14+1, 1 -FROM generate_series('2021-07-01 00:00:00'::timestamp, - '2021-08-17 00:02:00'::timestamp, '30 s'::interval) s; -SELECT compress_chunk(chunk) -FROM show_chunks('metric') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_36_chunk - _timescaledb_internal._dist_hyper_10_37_chunk - _timescaledb_internal._dist_hyper_10_38_chunk - _timescaledb_internal._dist_hyper_10_39_chunk - _timescaledb_internal._dist_hyper_10_40_chunk - _timescaledb_internal._dist_hyper_10_41_chunk - _timescaledb_internal._dist_hyper_10_42_chunk -(7 rows) - --- make sure we have chunks on all data nodes -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks where hypertable_name like 'metric'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-------------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+------------------------- - public | metric | _timescaledb_internal | _dist_hyper_10_36_chunk | time | timestamp with time zone | Wed Jun 30 17:00:00 2021 PDT | Wed Jul 07 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_37_chunk | time | timestamp with time zone | Wed Jul 07 17:00:00 2021 PDT | Wed Jul 14 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_38_chunk | time | timestamp with time zone | Wed Jul 14 17:00:00 2021 PDT | Wed Jul 21 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_39_chunk | time | timestamp with time zone | Wed Jul 21 17:00:00 2021 PDT | Wed Jul 28 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} - public | metric | _timescaledb_internal | _dist_hyper_10_40_chunk | time | timestamp with time zone | Wed Jul 28 17:00:00 2021 PDT | Wed Aug 04 17:00:00 2021 PDT | | | t | | {db_dist_compression_3} - public | metric | _timescaledb_internal | _dist_hyper_10_41_chunk | time | timestamp with time zone | Wed Aug 04 17:00:00 2021 PDT | Wed Aug 11 17:00:00 2021 PDT | | | t | | {db_dist_compression_1} - public | metric | _timescaledb_internal | _dist_hyper_10_42_chunk | time | timestamp with time zone | Wed Aug 11 17:00:00 2021 PDT | Wed Aug 18 17:00:00 2021 PDT | | | t | | {db_dist_compression_2} -(7 rows) - --- perform all combinations --- [IF NOT EXISTS] - [] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; --- [IF NOT EXISTS] - ["medium"] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; -NOTICE: column "medium" of relation "metric" already exists, skipping --- [] - [] -ALTER TABLE metric ADD COLUMN "medium_1" varchar; --- [] - ["medium_1"] -\set ON_ERROR_STOP 0 -ALTER TABLE metric ADD COLUMN "medium_1" varchar; -ERROR: column "medium_1" of relation "metric" already exists -SELECT * FROM metric limit 5; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+--------+---------- - Wed Jul 21 16:59:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:59:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:30 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:58:00 2021 PDT | 4.14 | 1 | | - Wed Jul 21 16:57:30 2021 PDT | 4.14 | 1 | | -(5 rows) - -SELECT * FROM metric where medium is not null; - time | val | dev_id | medium | medium_1 -------+-----+--------+--------+---------- -(0 rows) - --- INSERTs operate normally on the added column -INSERT INTO metric (time, val, dev_id, medium) -SELECT s.*, 3.14+1, 1, 'medium_value_text' -FROM generate_series('2021-08-18 00:00:00'::timestamp, - '2021-08-19 00:02:00'::timestamp, '30 s'::interval) s; -SELECT * FROM metric where medium is not null ORDER BY time LIMIT 1; - time | val | dev_id | medium | medium_1 -------------------------------+------+--------+-------------------+---------- - Wed Aug 18 00:00:00 2021 PDT | 4.14 | 1 | medium_value_text | -(1 row) - --- test alter_data_node(unvailable) with compressed chunks --- --- create compressed distributed hypertable -CREATE TABLE compressed(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (11,public,compressed,t) -(1 row) - --- insert data and get chunks distribution -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+--------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_1,db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT count(*) FROM compressed; - count -------- - 49 -(1 row) - --- make data node unavailable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -WARNING: altering data node is deprecated -WARNING: could not switch data node on 5 chunks - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55433,db_dist_compression_1,f) -(1 row) - -SET ROLE :ROLE_1; --- update compressed chunks -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; --- ensure that chunks associated with unavailable data node 1 --- are removed after being updated -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - ?column? | data_nodes ------------------------------------------------+----------------------------------------------- - _timescaledb_internal._dist_hyper_11_44_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_45_chunk | {db_dist_compression_2,db_dist_compression_3} - _timescaledb_internal._dist_hyper_11_46_chunk | {db_dist_compression_2,db_dist_compression_3} -(3 rows) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2', :'DATA_NODE_3'], $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- make data node available again -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,f) -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node ------------------------------------------------------------------ - (db_dist_compression_1,localhost,55432,db_dist_compression_1,t) -(1 row) - -SET ROLE :ROLE_1; --- ensure that stale chunks being dropped from data node 1 automatically -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - --- recompress chunks -CALL recompress_all_chunks('compressed', 3, true); -SELECT count(*) FROM compressed; - count -------- - 98 -(1 row) - -SELECT * from show_chunks('compressed'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_44_chunk - _timescaledb_internal._dist_hyper_11_45_chunk - _timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_compression_2]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_3]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_11_44_chunk -_timescaledb_internal._dist_hyper_11_45_chunk -_timescaledb_internal._dist_hyper_11_46_chunk -(3 rows) - - -NOTICE: [db_dist_compression_1]: SELECT * from show_chunks('compressed') -NOTICE: [db_dist_compression_1]: -show_chunks ------------ -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE compressed; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_copy_available_dns.out b/tsl/test/expected/dist_copy_available_dns.out deleted file mode 100644 index 07e2b1c416d..00000000000 --- a/tsl/test/expected/dist_copy_available_dns.out +++ /dev/null @@ -1,357 +0,0 @@ --- 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. --- Test distributed COPY with a bigger data set to help find rare effects. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE VIEW chunk_query_data_node AS -SELECT ch.hypertable_name, format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass AS chunk, ch.data_nodes, fs.srvname default_data_node - FROM timescaledb_information.chunks ch - INNER JOIN pg_foreign_table ft ON (format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass = ft.ftrelid) - INNER JOIN pg_foreign_server fs ON (ft.ftserver = fs.oid) - ORDER BY 1 DESC, 2 DESC; -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); --- Aim to about 100 partitions, the data is from 1995 to 2022. -select create_distributed_hypertable('uk_price_paid', 'date', chunk_time_interval => interval '270 day', replication_factor=>3); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "date" - create_distributed_hypertable -------------------------------- - (1,public,uk_price_paid,t) -(1 row) - -create table uk_price_paid_space2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space2', 'date', 'postcode2', 2, chunk_time_interval => interval '270 day', replication_factor => 2); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "postcode2" - create_distributed_hypertable ------------------------------------ - (2,public,uk_price_paid_space2,t) -(1 row) - -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_space2' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node -----------------------+----------------------------------------------+---------------------------+------------------- - uk_price_paid_space2 | _timescaledb_internal._dist_hyper_2_76_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_space2 | _timescaledb_internal._dist_hyper_2_75_chunk | {data_node_1,data_node_2} | data_node_1 - uk_price_paid_space2 | _timescaledb_internal._dist_hyper_2_74_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_space2 | _timescaledb_internal._dist_hyper_2_73_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_space2 | _timescaledb_internal._dist_hyper_2_72_chunk | {data_node_1,data_node_2} | data_node_1 -(5 rows) - -set timescaledb.max_open_chunks_per_insert = 1; -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count -------- - 10000 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_114_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_113_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_112_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_111_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_110_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 -(5 rows) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>false); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_1 | localhost | 55432 | db_dist_copy_available_dns_1 | f -(1 row) - -SET ROLE :ROLE_1; -set timescaledb.max_open_chunks_per_insert = 2; --- we will write to the same set of chunks and update AN metadata for down DN -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count -------- - 20000 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_114_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_113_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_112_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_111_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_110_chunk | {data_node_2,data_node_3} | data_node_2 -(5 rows) - -set timescaledb.max_open_chunks_per_insert = 1117; -WARNING: insert cache size is larger than hypertable chunk cache size -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>true); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_1 | localhost | 55432 | db_dist_copy_available_dns_1 | t -(1 row) - -SET ROLE :ROLE_1; -TRUNCATE uk_price_paid; -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count -------- - 10000 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_152_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_151_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_150_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_149_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_148_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 -(5 rows) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name like 'uk_price_paid%' order by hypertable_name; - hypertable_name | replication_factor -----------------------+-------------------- - uk_price_paid | 3 - uk_price_paid_space2 | 2 -(2 rows) - --- 0, 1, 2 rows -\copy uk_price_paid from stdin -select count(*) from uk_price_paid; - count -------- - 10000 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -1'; -select count(*) from uk_price_paid; - count -------- - 10001 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -2'; -select count(*) from uk_price_paid; - count -------- - 10003 -(1 row) - -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - count | sum | ?column? --------+------------+---------- - 10003 | 2055811013 | 205519 -(1 row) - --- Make binary file. -\copy (select * from uk_price_paid) to 'prices-10k.pgbinary' with (format binary); --- Binary input with binary data transfer. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -create table uk_price_paid_bin(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_bin', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (3,public,uk_price_paid_bin,t) -(1 row) - -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 10003 | 2055811013 | 205519 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node --------------------+-----------------------------------------------+---------------------------------------+------------------- - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_485_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_484_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_483_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_482_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_481_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 -(5 rows) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>false); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_1 | localhost | 55432 | db_dist_copy_available_dns_1 | f -(1 row) - -SET ROLE :ROLE_1; --- Text input with explicit format option and binary data transfer. This will --- update AN metadata for the down DN -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz' with (format text); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 20003 | 4111499026 | 205544 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node --------------------+-----------------------------------------------+---------------------------+------------------- - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_485_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_484_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_483_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_482_chunk | {data_node_2,data_node_3} | data_node_3 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_481_chunk | {data_node_2,data_node_3} | data_node_2 -(5 rows) - --- Text input with text data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 30003 | 6167187039 | 205552 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node --------------------+-----------------------------------------------+---------------------------+------------------- - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_485_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_484_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_483_chunk | {data_node_2,data_node_3} | data_node_2 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_482_chunk | {data_node_2,data_node_3} | data_node_3 - uk_price_paid_bin | _timescaledb_internal._dist_hyper_3_481_chunk | {data_node_2,data_node_3} | data_node_2 -(5 rows) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>true); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_1 | localhost | 55432 | db_dist_copy_available_dns_1 | t -(1 row) - -SET ROLE :ROLE_1; -TRUNCATE uk_price_paid; -SET timescaledb.enable_distributed_insert_with_copy=false; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - count | sum | ?column? --------+------------+---------- - 30003 | 6167187039 | 205552 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_523_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_522_chunk | {data_node_1,data_node_2,data_node_3} | data_node_3 - uk_price_paid | _timescaledb_internal._dist_hyper_1_521_chunk | {data_node_1,data_node_2,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_520_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_519_chunk | {data_node_1,data_node_2,data_node_3} | data_node_2 -(5 rows) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_2', available=>false); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_2 | localhost | 55432 | db_dist_copy_available_dns_2 | f -(1 row) - -SET ROLE :ROLE_1; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - count | sum | ?column? --------+-------------+---------- - 60006 | 12334374078 | 205552 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_523_chunk | {data_node_1,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_522_chunk | {data_node_1,data_node_3} | data_node_3 - uk_price_paid | _timescaledb_internal._dist_hyper_1_521_chunk | {data_node_1,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_520_chunk | {data_node_1,data_node_3} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_519_chunk | {data_node_1,data_node_3} | data_node_1 -(5 rows) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_2', available=>true); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_2 | localhost | 55432 | db_dist_copy_available_dns_2 | t -(1 row) - -SET ROLE :ROLE_1; -truncate uk_price_paid; -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_3', available=>false); -WARNING: altering data node is deprecated - node_name | host | port | database | available --------------+-----------+-------+------------------------------+----------- - data_node_3 | localhost | 55432 | db_dist_copy_available_dns_3 | f -(1 row) - -SET ROLE :ROLE_1; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - count | sum | ?column? --------+-------------+---------- - 60006 | 12334374078 | 205552 -(1 row) - -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - hypertable_name | chunk | data_nodes | default_data_node ------------------+-----------------------------------------------+---------------------------+------------------- - uk_price_paid | _timescaledb_internal._dist_hyper_1_561_chunk | {data_node_1,data_node_2} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_560_chunk | {data_node_1,data_node_2} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_559_chunk | {data_node_1,data_node_2} | data_node_1 - uk_price_paid | _timescaledb_internal._dist_hyper_1_558_chunk | {data_node_1,data_node_2} | data_node_2 - uk_price_paid | _timescaledb_internal._dist_hyper_1_557_chunk | {data_node_1,data_node_2} | data_node_2 -(5 rows) - --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_copy_format_long.out b/tsl/test/expected/dist_copy_format_long.out deleted file mode 100644 index b462a110556..00000000000 --- a/tsl/test/expected/dist_copy_format_long.out +++ /dev/null @@ -1,119 +0,0 @@ --- 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. --- Test distributed COPY with text/binary format for input and for data transfer --- to data nodes. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- buffer a lot of rows per message to test buffer expansion -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD copy_rows_per_message '1000'); -SET ROLE :ROLE_1; --- Aim to about 100 partitions, the data is from 1995 to 2022. -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); -select create_distributed_hypertable('uk_price_paid', 'date', 'postcode2', - chunk_time_interval => interval '270 day'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "date" - create_distributed_hypertable -------------------------------- - (1,public,uk_price_paid,t) -(1 row) - --- Populate. -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - count | sum | ?column? --------+------------+---------- - 10000 | 2055688013 | 205568 -(1 row) - -select count(*) from show_chunks('uk_price_paid'); - count -------- - 114 -(1 row) - --- Make binary file. -\copy (select * from uk_price_paid) to 'prices-10k.pgbinary' with (format binary); --- Binary input with binary data transfer. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -create table uk_price_paid_bin(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_bin', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (2,public,uk_price_paid_bin,t) -(1 row) - -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 10000 | 2055688013 | 205568 -(1 row) - --- Text input with explicit format option and binary data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz' with (format text); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 20000 | 4111376026 | 205568 -(1 row) - --- Binary input with text data transfer. Doesn't work. -set timescaledb.dist_copy_transfer_format = 'text'; -\set ON_ERROR_STOP off -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -ERROR: remote copy does not support binary input in combination with text transfer to data nodes -\set ON_ERROR_STOP on --- Text input with text data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - count | sum | ?column? --------+------------+---------- - 30000 | 6167064039 | 205568 -(1 row) - --- Nonsensical settings -set timescaledb.dist_copy_transfer_format = 'binary'; -set timescaledb.enable_connection_binary_data = false; -\set ON_ERROR_STOP off -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -ERROR: the requested binary format for COPY data transfer is disabled by the settings -\set ON_ERROR_STOP on --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_copy_long.out b/tsl/test/expected/dist_copy_long.out deleted file mode 100644 index 5d2af08e2a9..00000000000 --- a/tsl/test/expected/dist_copy_long.out +++ /dev/null @@ -1,219 +0,0 @@ --- 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. --- Test distributed COPY with a bigger data set to help find rare effects. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -WARNING: adding data node is deprecated - ?column? ----------- - 1 -(1 row) - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DN_DBNAME_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DN_DBNAME_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DN_DBNAME_3 SET parallel_setup_cost TO 1; --- make sure query push-down is enabled -ALTER DATABASE :DN_DBNAME_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DN_DBNAME_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DN_DBNAME_3 SET enable_partitionwise_aggregate TO true; -SET enable_partitionwise_aggregate TO true; -SET ROLE :ROLE_1; -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); --- Aim to about 100 partitions, the data is from 1995 to 2022. -select create_distributed_hypertable('uk_price_paid', 'date', chunk_time_interval => interval '270 day'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "date" - create_distributed_hypertable -------------------------------- - (1,public,uk_price_paid,t) -(1 row) - -create table uk_price_paid_space2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space2', 'date', 'postcode2', 2, chunk_time_interval => interval '270 day'); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "postcode2" - create_distributed_hypertable ------------------------------------ - (2,public,uk_price_paid_space2,t) -(1 row) - -create table uk_price_paid_space10(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space10', 'date', 'postcode2', 10, chunk_time_interval => interval '270 day'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable ------------------------------------- - (3,public,uk_price_paid_space10,t) -(1 row) - -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space2; - count -------- - 10000 -(1 row) - -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space2; - count -------- - 20000 -(1 row) - -\copy uk_price_paid_space10 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space10; - count -------- - 10000 -(1 row) - -\copy uk_price_paid_space10 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space10; - count -------- - 20000 -(1 row) - -set timescaledb.max_open_chunks_per_insert = 1; -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 100000 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 200000 -(1 row) - -truncate uk_price_paid; -set timescaledb.max_open_chunks_per_insert = 2; -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 100000 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 200000 -(1 row) - -truncate uk_price_paid; -set timescaledb.max_open_chunks_per_insert = 1117; -WARNING: insert cache size is larger than hypertable chunk cache size -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 100000 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - count --------- - 200000 -(1 row) - --- Different replication factors -create table uk_price_paid_r2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_r2', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (4,public,uk_price_paid_r2,t) -(1 row) - -create table uk_price_paid_r3(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_r3', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (5,public,uk_price_paid_r3,t) -(1 row) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name like 'uk_price_paid%' order by hypertable_name; - hypertable_name | replication_factor ------------------------+-------------------- - uk_price_paid | 1 - uk_price_paid_r2 | 2 - uk_price_paid_r3 | 3 - uk_price_paid_space10 | 1 - uk_price_paid_space2 | 1 -(5 rows) - -\copy uk_price_paid_r2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_r2; - count -------- - 10000 -(1 row) - -\copy uk_price_paid_r3 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_r3; - count -------- - 10000 -(1 row) - --- 0, 1, 2 rows -\copy uk_price_paid from stdin -select count(*) from uk_price_paid; - count --------- - 200000 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -1'; -select count(*) from uk_price_paid; - count --------- - 200001 -(1 row) - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -2'; -select count(*) from uk_price_paid; - count --------- - 200003 -(1 row) - --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_ddl.out b/tsl/test/expected/dist_ddl.out deleted file mode 100644 index 7cfa0428a7c..00000000000 --- a/tsl/test/expected/dist_ddl.out +++ /dev/null @@ -1,3604 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -CREATE SCHEMA some_schema AUTHORIZATION :ROLE_1; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ----------------+---------------+--------------+------------------+------------------- - db_dist_ddl_1 | db_dist_ddl_1 | t | t | t - db_dist_ddl_2 | db_dist_ddl_2 | t | t | t - db_dist_ddl_3 | db_dist_ddl_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Presence of non-distributed hypertables on data nodes should not cause issues -CALL distributed_exec('CREATE TABLE local(time timestamptz, measure int)', ARRAY[:'DATA_NODE_1',:'DATA_NODE_3']); -CALL distributed_exec($$ SELECT create_hypertable('local', 'time') $$, ARRAY[:'DATA_NODE_1',:'DATA_NODE_3']); --- Import testsupport.sql file to data nodes -\unset ECHO -SET ROLE :ROLE_1; -CREATE TABLE disttable(time timestamptz, device int, color int CONSTRAINT color_check CHECK (color > 0), temp float); -CREATE UNIQUE INDEX disttable_pk ON disttable(time, temp); --- CREATE TABLE -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'temp', replication_factor => 3); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - -SELECT * FROM test.show_columns('disttable'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | f - color | integer | f - temp | double precision | f -(4 rows) - -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated --------------+------+---------+-------+-------------+------------+----------+----------- - color_check | c | {color} | - | (color > 0) | f | f | t -(1 row) - -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace --------------------------+-------------+------+--------+---------+-----------+------------ - disttable_pk | {time,temp} | | t | f | f | - disttable_temp_time_idx | {temp,time} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(3 rows) - -SELECT * FROM test.show_triggers('disttable'); - Trigger | Type | Function --------------------+------+--------------------------------------- - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_columns('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.show_indexes('disttable'); -SELECT * FROM test.show_triggers('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_1]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -color |integer |f -temp |double precision |f -(4 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_pk |{time,temp}| |t |f |f | -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(3 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_triggers('disttable') -NOTICE: [db_dist_ddl_1]: -Trigger |Type|Function ------------------+----+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_2]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -color |integer |f -temp |double precision |f -(4 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_pk |{time,temp}| |t |f |f | -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(3 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_triggers('disttable') -NOTICE: [db_dist_ddl_2]: -Trigger |Type|Function ------------------+----+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_3]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -color |integer |f -temp |double precision |f -(4 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_pk |{time,temp}| |t |f |f | -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(3 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_triggers('disttable') -NOTICE: [db_dist_ddl_3]: -Trigger |Type|Function ------------------+----+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - - remote_exec -------------- - -(1 row) - --- ADD CONSTRAINT -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated ---------------+------+----------+-------+--------------+------------+----------+----------- - color_check | c | {color} | - | (color > 0) | f | f | t - device_check | c | {device} | - | (device > 0) | f | f | t -(2 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -color_check |c |{color} |- |(color > 0) |f |f |t -device_check|c |{device}|- |(device > 0)|f |f |t -(2 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -color_check |c |{color} |- |(color > 0) |f |f |t -device_check|c |{device}|- |(device > 0)|f |f |t -(2 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -color_check |c |{color} |- |(color > 0) |f |f |t -device_check|c |{device}|- |(device > 0)|f |f |t -(2 rows) - - - remote_exec -------------- - -(1 row) - --- DROP CONSTRAINT -ALTER TABLE disttable DROP CONSTRAINT device_check; -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated --------------+------+---------+-------+-------------+------------+----------+----------- - color_check | c | {color} | - | (color > 0) | f | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated ------------+----+-------+-----+-----------+----------+--------+--------- -color_check|c |{color}|- |(color > 0)|f |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - --- DROP CONSTRAINT pre-created -ALTER TABLE disttable DROP CONSTRAINT color_check; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- DROP COLUMN -ALTER TABLE disttable DROP COLUMN color; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_columns('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_1]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -temp |double precision |f -(3 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_2]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -temp |double precision |f -(3 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_3]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -temp |double precision |f -(3 rows) - - - remote_exec -------------- - -(1 row) - --- ADD COLUMN -ALTER TABLE disttable ADD COLUMN description text; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_columns('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_1]: -Column |Type |NotNull ------------+------------------------+------- -time |timestamp with time zone|t -device |integer |f -temp |double precision |f -description|text |f -(4 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_2]: -Column |Type |NotNull ------------+------------------------+------- -time |timestamp with time zone|t -device |integer |f -temp |double precision |f -description|text |f -(4 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_columns('disttable') -NOTICE: [db_dist_ddl_3]: -Column |Type |NotNull ------------+------------------------+------- -time |timestamp with time zone|t -device |integer |f -temp |double precision |f -description|text |f -(4 rows) - - - remote_exec -------------- - -(1 row) - --- CREATE INDEX -CREATE INDEX disttable_description_idx ON disttable (description); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace --------------------------+-------------+----+------+-------+---------+---------- -disttable_description_idx|{description}| |f |f |f | -disttable_pk |{time,temp} | |t |f |f | -disttable_temp_time_idx |{temp,time} | |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(4 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace --------------------------+-------------+----+------+-------+---------+---------- -disttable_description_idx|{description}| |f |f |f | -disttable_pk |{time,temp} | |t |f |f | -disttable_temp_time_idx |{temp,time} | |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(4 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace --------------------------+-------------+----+------+-------+---------+---------- -disttable_description_idx|{description}| |f |f |f | -disttable_pk |{time,temp} | |t |f |f | -disttable_temp_time_idx |{temp,time} | |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(4 rows) - - - remote_exec -------------- - -(1 row) - --- TRUNCATE -CREATE TABLE non_disttable1(time timestamptz); -CREATE TABLE non_disttable2(time timestamptz); -SELECT create_hypertable('non_disttable2', 'time'); -NOTICE: adding not-null constraint to column "time" - create_hypertable ------------------------------ - (2,public,non_disttable2,t) -(1 row) - --- Truncating two non-distribued hypertables should be OK. -TRUNCATE non_disttable1, non_disttable2; --- Truncating one distributed hypertable should be OK -TRUNCATE disttable; --- RENAME TO -ALTER TABLE disttable RENAME TO disttable2; -SELECT 1 FROM pg_tables WHERE tablename = 'disttable2'; - ?column? ----------- - 1 -(1 row) - -\c :DATA_NODE_1 -SELECT 1 FROM pg_tables WHERE tablename = 'disttable2'; - ?column? ----------- - 1 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; -ALTER TABLE disttable2 RENAME TO disttable; -SELECT 1 FROM pg_tables WHERE tablename = 'disttable'; - ?column? ----------- - 1 -(1 row) - -\c :DATA_NODE_1 -SELECT 1 FROM pg_tables WHERE tablename = 'disttable'; - ?column? ----------- - 1 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; -SET timescaledb.hide_data_node_name_in_errors = 'on'; --- SET SCHEMA -\set ON_ERROR_STOP 0 -ALTER TABLE disttable SET SCHEMA some_unexist_schema; -ERROR: schema "some_unexist_schema" does not exist -\set ON_ERROR_STOP 1 --- some_schema was not created on data nodes -\set ON_ERROR_STOP 0 -ALTER TABLE disttable SET SCHEMA some_schema; -ERROR: []: schema "some_schema" does not exist -\set ON_ERROR_STOP 1 --- OWNER TO -RESET ROLE; -ALTER TABLE disttable OWNER TO :ROLE_2; -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable'; - tableowner -------------- - test_role_2 -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_1]: -tableowner ------------ -test_role_2 -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_2]: -tableowner ------------ -test_role_2 -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_3]: -tableowner ------------ -test_role_2 -(1 row) - - - remote_exec -------------- - -(1 row) - -ALTER TABLE disttable OWNER TO :ROLE_1; -SET ROLE :ROLE_1; --- Test unsupported operations on distributed hypertable -\set ON_ERROR_STOP 0 --- test set_replication_factor on non-hypertable -SELECT * FROM set_replication_factor('non_disttable1', 1); -ERROR: table "non_disttable1" is not a hypertable --- test set_replication_factor on non-distributed -SELECT * FROM set_replication_factor('non_disttable2', 1); -ERROR: hypertable "non_disttable2" is not distributed --- test set_replication_factor on NULL hypertable -SELECT * FROM set_replication_factor(NULL, 1); -ERROR: invalid hypertable: cannot be NULL --- Combining one distributed hypertable with any other tables should --- be blocked since not all nodes might have all tables and we --- currently don't rewrite the command. -TRUNCATE disttable, non_disttable1; -ERROR: operation not supported on distributed hypertable -TRUNCATE disttable, non_disttable2; -ERROR: operation not supported on distributed hypertable -CLUSTER disttable USING disttable_description_idx; -ERROR: operation not supported on distributed hypertable -DROP TABLE non_disttable1, disttable; -ERROR: cannot drop a hypertable along with other objects -DROP TABLE disttable, non_disttable2; -ERROR: cannot drop a hypertable along with other objects -DROP TABLE disttable, disttable; -ERROR: cannot drop a hypertable along with other objects -\set ON_ERROR_STOP 1 ----------------------------------------------------------------------------------------- --- Test column type change, renaming columns, constraints, indexes, and REINDEX command. ----------------------------------------------------------------------------------------- -ALTER TABLE disttable ALTER COLUMN description TYPE VARCHAR(10); -ALTER TABLE disttable ADD COLUMN float_col float; -ALTER TABLE disttable ALTER COLUMN float_col TYPE INT USING float_col::int; -\set ON_ERROR_STOP 0 --- Changing the type of a hash-partitioned column should not be supported -ALTER TABLE disttable ALTER COLUMN temp TYPE numeric; -ERROR: cannot change the type of a hash-partitioned column -\set ON_ERROR_STOP 1 --- Should be able to change if not hash partitioned though -ALTER TABLE disttable ALTER COLUMN time TYPE timestamp; -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2, 'test'), - ('2017-01-01 09:11', 3, 4.3, 'test'), - ('2017-01-01 08:01', 1, 7.3, 'test'), - ('2017-01-02 08:01', 2, 0.23, 'test'), - ('2018-07-02 08:01', 87, 0.0, 'test'), - ('2018-07-01 06:01', 13, 3.1, 'test'), - ('2018-07-01 09:11', 90, 10303.12, 'test'), - ('2018-07-01 08:01', 29, 64, 'test'); -SELECT * FROM show_chunks('disttable'); - show_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk -(5 rows) - --- Replica identity -SELECT * FROM test.remote_exec(NULL, -$$ - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname; - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_1]: -relname |relreplident ----------+------------ -disttable|d -(1 row) - - -NOTICE: [db_dist_ddl_1]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_1]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|d -_dist_hyper_1_2_chunk|d -_dist_hyper_1_3_chunk|d -_dist_hyper_1_4_chunk|d -_dist_hyper_1_5_chunk|d -(5 rows) - - -NOTICE: [db_dist_ddl_2]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_2]: -relname |relreplident ----------+------------ -disttable|d -(1 row) - - -NOTICE: [db_dist_ddl_2]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_2]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|d -_dist_hyper_1_2_chunk|d -_dist_hyper_1_3_chunk|d -_dist_hyper_1_4_chunk|d -_dist_hyper_1_5_chunk|d -(5 rows) - - -NOTICE: [db_dist_ddl_3]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_3]: -relname |relreplident ----------+------------ -disttable|d -(1 row) - - -NOTICE: [db_dist_ddl_3]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_3]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|d -_dist_hyper_1_2_chunk|d -_dist_hyper_1_3_chunk|d -_dist_hyper_1_4_chunk|d -_dist_hyper_1_5_chunk|d -(5 rows) - - - remote_exec -------------- - -(1 row) - -ALTER TABLE disttable REPLICA IDENTITY FULL; -SELECT * FROM test.remote_exec(NULL, -$$ - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname; - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_1]: -relname |relreplident ----------+------------ -disttable|f -(1 row) - - -NOTICE: [db_dist_ddl_1]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_1]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|f -_dist_hyper_1_2_chunk|f -_dist_hyper_1_3_chunk|f -_dist_hyper_1_4_chunk|f -_dist_hyper_1_5_chunk|f -(5 rows) - - -NOTICE: [db_dist_ddl_2]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_2]: -relname |relreplident ----------+------------ -disttable|f -(1 row) - - -NOTICE: [db_dist_ddl_2]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_2]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|f -_dist_hyper_1_2_chunk|f -_dist_hyper_1_3_chunk|f -_dist_hyper_1_4_chunk|f -_dist_hyper_1_5_chunk|f -(5 rows) - - -NOTICE: [db_dist_ddl_3]: - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname -NOTICE: [db_dist_ddl_3]: -relname |relreplident ----------+------------ -disttable|f -(1 row) - - -NOTICE: [db_dist_ddl_3]: - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname -NOTICE: [db_dist_ddl_3]: -relname |relreplident ----------------------+------------ -_dist_hyper_1_1_chunk|f -_dist_hyper_1_2_chunk|f -_dist_hyper_1_3_chunk|f -_dist_hyper_1_4_chunk|f -_dist_hyper_1_5_chunk|f -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Rename column -ALTER TABLE disttable RENAME COLUMN description TO descr; -SELECT * FROM test.show_columns('disttable') -WHERE "Column"='descr'; - Column | Type | NotNull ---------+-------------------+--------- - descr | character varying | f -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, - (SELECT "Column" AS col FROM test.show_columns(chunk.relid) WHERE "Column"='descr') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: - SELECT chunk.relid AS chunk_relid, - (SELECT "Column" AS col FROM test.show_columns(chunk.relid) WHERE "Column"='descr') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk - -NOTICE: [db_dist_ddl_1]: -chunk_relid |col --------------------------------------------+----- -_timescaledb_internal._dist_hyper_1_1_chunk|descr -(1 row) - - - remote_exec -------------- - -(1 row) - --- Rename constraint -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); -ALTER TABLE disttable RENAME CONSTRAINT device_check TO device_chk; -SELECT * FROM test.show_constraints('disttable') -WHERE "Constraint"='device_chk'; - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+----------+-------+--------------+------------+----------+----------- - device_chk | c | {device} | - | (device > 0) | f | f | t -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, - (SELECT "Constraint" AS constr FROM test.show_constraints(chunk.relid) WHERE "Constraint"='device_chk') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: - SELECT chunk.relid AS chunk_relid, - (SELECT "Constraint" AS constr FROM test.show_constraints(chunk.relid) WHERE "Constraint"='device_chk') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk - -NOTICE: [db_dist_ddl_1]: -chunk_relid |constr --------------------------------------------+---------- -_timescaledb_internal._dist_hyper_1_1_chunk|device_chk -(1 row) - - - remote_exec -------------- - -(1 row) - --- Rename index -ALTER INDEX disttable_description_idx RENAME to disttable_descr_idx; -SELECT * FROM test.show_indexes('disttable') -WHERE "Index"='disttable_descr_idx'::regclass; - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------+---------------+------+--------+---------+-----------+------------ - disttable_descr_idx | {description} | | f | f | f | -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, (test.show_indexes(chunk.relid)).* - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: - SELECT chunk.relid AS chunk_relid, (test.show_indexes(chunk.relid)).* - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk - -NOTICE: [db_dist_ddl_1]: -chunk_relid |Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace --------------------------------------------+-------------------------------------------------------------------+-------------+----+------+-------+---------+---------- -_timescaledb_internal._dist_hyper_1_1_chunk|_timescaledb_internal._dist_hyper_1_1_chunk_disttable_descr_idx |{description}| |f |f |f | -_timescaledb_internal._dist_hyper_1_1_chunk|_timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk |{time,temp} | |t |f |f | -_timescaledb_internal._dist_hyper_1_1_chunk|_timescaledb_internal._dist_hyper_1_1_chunk_disttable_temp_time_idx|{temp,time} | |f |f |f | -_timescaledb_internal._dist_hyper_1_1_chunk|_timescaledb_internal._dist_hyper_1_1_chunk_disttable_time_idx |{time} | |f |f |f | -(4 rows) - - - remote_exec -------------- - -(1 row) - --- Test REINDEX command with distributed hypertable -\c :DATA_NODE_1 -SELECT * FROM test.show_indexes('_timescaledb_internal._dist_hyper_1_1_chunk'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ - _timescaledb_internal._dist_hyper_1_1_chunk_disttable_descr_idx | {description} | | f | f | f | - _timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk | {time,temp} | | t | f | f | - _timescaledb_internal._dist_hyper_1_1_chunk_disttable_temp_time_idx | {temp,time} | | f | f | f | - _timescaledb_internal._dist_hyper_1_1_chunk_disttable_time_idx | {time} | | f | f | f | -(4 rows) - -SELECT pg_relation_filepath('_timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk'::regclass::oid) AS oid_before_reindex \gset -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; -REINDEX TABLE disttable; -REINDEX (VERBOSE) TABLE disttable; -\c :DATA_NODE_1 -SELECT pg_relation_filepath('_timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk'::regclass::oid) AS oid_after_reindex \gset -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; --- expect chunk index oid to change after the reindex operation -SELECT :'oid_before_reindex' <> :'oid_after_reindex'; - ?column? ----------- - t -(1 row) - --- CREATE/DROP TRIGGER -CREATE OR REPLACE FUNCTION test_trigger() -RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN -RETURN OLD; -END -$BODY$; -CREATE TRIGGER disttable_trigger_test -BEFORE INSERT ON disttable -FOR EACH ROW EXECUTE FUNCTION test_trigger(); -DROP TRIGGER disttable_trigger_test on disttable; -DROP FUNCTION test_trigger; -CALL distributed_exec($$ DROP FUNCTION test_trigger $$); --- DROP INDEX -\set ON_ERROR_STOP 0 -DROP INDEX disttable_description_idx, disttable_pk; -ERROR: cannot drop a hypertable index along with other objects -\set ON_ERROR_STOP 1 -DROP INDEX disttable_descr_idx; -DROP INDEX disttable_pk; -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace --------------------------+-------------+------+--------+---------+-----------+------------ - disttable_temp_time_idx | {temp,time} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(2 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('disttable') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace ------------------------+-----------+----+------+-------+---------+---------- -disttable_temp_time_idx|{temp,time}| |f |f |f | -disttable_time_idx |{time} | |f |f |f | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- DROP TABLE -DROP TABLE disttable; -SELECT * FROM test.remote_exec(NULL, $$ SELECT 1 FROM pg_tables WHERE tablename = 'disttable' $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT 1 FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_1]: -?column? --------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT 1 FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_2]: -?column? --------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT 1 FROM pg_tables WHERE tablename = 'disttable' -NOTICE: [db_dist_ddl_3]: -?column? --------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE non_disttable1; -DROP TABLE non_disttable2; --- CREATE SCHEMA tests -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE SCHEMA dist_schema AUTHORIZATION :ROLE_1; --- make sure schema has been created on each data node -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_1]: -nspname |usename ------------+----------- -dist_schema|test_role_1 -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_2]: -nspname |usename ------------+----------- -dist_schema|test_role_1 -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_3]: -nspname |usename ------------+----------- -dist_schema|test_role_1 -(1 row) - - - remote_exec -------------- - -(1 row) - -CREATE TABLE dist_schema.some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('dist_schema.some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 3 | dist_schema | some_dist_table | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_1]: -schemaname |tablename ------------+--------------- -dist_schema|some_dist_table -(1 row) - - -NOTICE: [db_dist_ddl_2]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_2]: -schemaname |tablename ------------+--------------- -dist_schema|some_dist_table -(1 row) - - -NOTICE: [db_dist_ddl_3]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_3]: -schemaname |tablename ------------+--------------- -dist_schema|some_dist_table -(1 row) - - - remote_exec -------------- - -(1 row) - --- DROP SCHEMA -DROP SCHEMA dist_schema CASCADE; -NOTICE: drop cascades to table dist_schema.some_dist_table -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_1]: -schemaname|tablename -----------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_2]: -schemaname|tablename -----------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_3]: -schemaname|tablename -----------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- make sure schema has been dropped on each data node -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_1]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_2]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema' -NOTICE: [db_dist_ddl_3]: -nspname|usename --------+------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- make sure empty schema schema has been created and then dropped on each data node -CREATE SCHEMA dist_schema_2; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_1]: -nspname |usename --------------+------------------ -dist_schema_2|cluster_super_user -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_2]: -nspname |usename --------------+------------------ -dist_schema_2|cluster_super_user -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_3]: -nspname |usename --------------+------------------ -dist_schema_2|cluster_super_user -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP SCHEMA dist_schema_2; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_1]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_2]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_3]: -nspname|usename --------+------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- transactional schema create/drop with local table -BEGIN; -CREATE SCHEMA dist_schema_3; -CREATE TABLE dist_schema_3.some_dist_table(time timestamptz, device int); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_1]: -nspname |usename --------------+------------------ -dist_schema_3|cluster_super_user -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_2]: -nspname |usename --------------+------------------ -dist_schema_3|cluster_super_user -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_3]: -nspname |usename --------------+------------------ -dist_schema_3|cluster_super_user -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP SCHEMA dist_schema_3 CASCADE; -NOTICE: drop cascades to table dist_schema_3.some_dist_table -ROLLBACK; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_1]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_2]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3' -NOTICE: [db_dist_ddl_3]: -nspname|usename --------+------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- ALTER SCHEMA RENAME TO -CREATE SCHEMA dist_schema; -CREATE TABLE dist_schema.some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('dist_schema.some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 4 | dist_schema | some_dist_table | t -(1 row) - -ALTER SCHEMA dist_schema RENAME TO dist_schema_2; -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_1]: -schemaname |tablename --------------+--------------- -dist_schema_2|some_dist_table -(1 row) - - -NOTICE: [db_dist_ddl_2]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_2]: -schemaname |tablename --------------+--------------- -dist_schema_2|some_dist_table -(1 row) - - -NOTICE: [db_dist_ddl_3]: SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' -NOTICE: [db_dist_ddl_3]: -schemaname |tablename --------------+--------------- -dist_schema_2|some_dist_table -(1 row) - - - remote_exec -------------- - -(1 row) - --- ALTER SCHEMA OWNER TO -ALTER SCHEMA dist_schema_2 OWNER TO :ROLE_1; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_1]: -nspname |usename --------------+----------- -dist_schema_2|test_role_1 -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_2]: -nspname |usename --------------+----------- -dist_schema_2|test_role_1 -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2' -NOTICE: [db_dist_ddl_3]: -nspname |usename --------------+----------- -dist_schema_2|test_role_1 -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP SCHEMA dist_schema_2 CASCADE; -NOTICE: drop cascades to table dist_schema_2.some_dist_table --- DROP column cascades to index drop -CREATE TABLE some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 5 | public | some_dist_table | t -(1 row) - -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - - remote_exec -------------- - -(1 row) - -ALTER TABLE some_dist_table DROP COLUMN device; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- Creation of foreign key on distributed hypertable table will lead --- to error, since non_htable is local -CREATE TABLE non_htable (id int PRIMARY KEY); -CREATE TABLE some_dist_table(time timestamptz, device int REFERENCES non_htable(id)); -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -$$); -WARNING: distributed hypertable "some_dist_table" has a foreign key to a non-distributed table -NOTICE: adding not-null constraint to column "time" -ERROR: [db_dist_ddl_x]: relation "non_htable" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE some_dist_table; -DROP TABLE non_htable; --- Test disabling DDL commands on global objects --- -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; -SET client_min_messages TO DEBUG1; --- CREATE SCHEMA -CREATE SCHEMA schema_global; -LOG: statement: CREATE SCHEMA schema_global; -DEBUG: skipping dist DDL on object: CREATE SCHEMA schema_global; --- Ensure SCHEMA is not created on data nodes -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global'; -$$); -LOG: statement: SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_1]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_2]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_3]: -nspname|usename --------+------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- RENAME SCHEMA -ALTER SCHEMA schema_global RENAME TO schema_global_2; -LOG: statement: ALTER SCHEMA schema_global RENAME TO schema_global_2; -DEBUG: skipping dist DDL on object: ALTER SCHEMA schema_global RENAME TO schema_global_2; --- ALTER SCHEMA OWNER TO -ALTER SCHEMA schema_global_2 OWNER TO :ROLE_1; -LOG: statement: ALTER SCHEMA schema_global_2 OWNER TO test_role_1; -DEBUG: skipping dist DDL on object: ALTER SCHEMA schema_global_2 OWNER TO test_role_1; --- REASSIGN OWNED BY TO -REASSIGN OWNED BY :ROLE_1 TO :ROLE_1; -LOG: statement: REASSIGN OWNED BY test_role_1 TO test_role_1; -DEBUG: skipping dist DDL on object: REASSIGN OWNED BY test_role_1 TO test_role_1; --- Reset earlier to avoid different debug output between PG versions -RESET client_min_messages; -LOG: statement: RESET client_min_messages; --- DROP OWNED BY schema_global_2 -DROP OWNED BY :ROLE_1; --- DROP SCHEMA -CREATE SCHEMA schema_global; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_1]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_2]: -nspname|usename --------+------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global' -NOTICE: [db_dist_ddl_3]: -nspname|usename --------+------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP SCHEMA schema_global; -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; --- Transactional DDL tests --- Single-statement transactions --- BEGIN/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 7 | public | some_dist_table | t -(1 row) - -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+----------+------+--------+---------+-----------+------------ - some_dist_device_idx | {device} | | f | f | f | - some_dist_table_time_idx | {time} | | f | f | f | -(2 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 8 | public | some_dist_table | t -(1 row) - -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+---------+------+--------+---------+-----------+------------ - some_dist_table_time_idx | {time} | | f | f | f | -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- DDL with multiple sub-commands (ALTER) -BEGIN; -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_distributed_hypertable('some_dist_table', 'time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 9 | public | some_dist_table | t -(1 row) - -\set ON_ERROR_STOP 0 --- Mixing SET and other options not supported. This is to protect --- against mixing custom (compression) options with other --- sub-commands. -ALTER TABLE some_dist_table SET (fillfactor = 10), -ADD CONSTRAINT device_check CHECK (device > 0); -ERROR: ALTER TABLE SET does not support multiple clauses -\set ON_ERROR_STOP 1 -ROLLBACK; --- Multi-statement transactions --- BEGIN/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 10 | public | some_dist_table | t -(1 row) - -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+----------+------+--------+---------+-----------+------------ - some_dist_device_idx | {device} | | f | f | f | - some_dist_table_time_idx | {time} | | f | f | f | -(2 rows) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated ---------------+------+----------+-------+--------------+------------+----------+----------- - device_check | c | {device} | - | (device > 0) | f | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 11 | public | some_dist_table | t -(1 row) - -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+---------+------+--------+---------+-----------+------------ - some_dist_table_time_idx | {time} | | f | f | f | -(1 row) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- Nested transactions --- BEGIN/BEGIN/COMMIT/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 12 | public | some_dist_table | t -(1 row) - -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+----------+------+--------+---------+-----------+------------ - some_dist_device_idx | {device} | | f | f | f | - some_dist_table_time_idx | {time} | | f | f | f | -(2 rows) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated ---------------+------+----------+-------+--------------+------------+----------+----------- - device_check | c | {device} | - | (device > 0) | f | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns |Index|Expr |Deferrable|Deferred|Validated -------------+----+--------+-----+------------+----------+--------+--------- -device_check|c |{device}|- |(device > 0)|f |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/BEGIN/ROLLBACK/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 13 | public | some_dist_table | t -(1 row) - -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT b; -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+----------+------+--------+---------+-----------+------------ - some_dist_device_idx | {device} | | f | f | f | - some_dist_table_time_idx | {time} | | f | f | f | -(2 rows) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns |Expr|Unique|Primary|Exclusion|Tablespace -------------------------+--------+----+------+-------+---------+---------- -some_dist_device_idx |{device}| |f |f |f | -some_dist_table_time_idx|{time} | |f |f |f | -(2 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/BEGIN/COMMIT/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 14 | public | some_dist_table | t -(1 row) - -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+---------+------+--------+---------+-----------+------------ - some_dist_table_time_idx | {time} | | f | f | f | -(1 row) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/BEGIN/ROLLBACK/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 15 | public | some_dist_table | t -(1 row) - -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT b; -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+---------+------+--------+---------+-----------+------------ - some_dist_table_time_idx | {time} | | f | f | f | -(1 row) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- BEGIN/BEGIN/ABORT/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 16 | public | some_dist_table | t -(1 row) - -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -\set ON_ERROR_STOP 0 -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ERROR: constraint "device_check" for relation "some_dist_table" already exists -\set ON_ERROR_STOP 1 -ROLLBACK TO SAVEPOINT b; -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------------+---------+------+--------+---------+-----------+------------ - some_dist_table_time_idx | {time} | | f | f | f | -(1 row) - -SELECT * FROM test.show_constraints('some_dist_table'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_indexes('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Index |Columns|Expr|Unique|Primary|Exclusion|Tablespace -------------------------+-------+----+------+-------+---------+---------- -some_dist_table_time_idx|{time} | |f |f |f | -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('some_dist_table') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE some_dist_table; --- Test chunks updates -CREATE TABLE disttable(time timestamptz, device int, color int CONSTRAINT color_check CHECK (color > 0), temp float); -CREATE UNIQUE INDEX disttable_pk ON disttable(time); -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 17 | public | disttable | t -(1 row) - -INSERT INTO disttable VALUES ('2017-01-01 06:01', 0, 1, 0.0); -SELECT show_chunks('disttable'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_17_6_chunk -(1 row) - -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated --------------+------+---------+-------+-------------+------------+----------+----------- - color_check | c | {color} | - | (color > 0) | f | f | t -(1 row) - -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated ---------------+------+---------+-------+------------------------------------------------------------------------------------------------------------------------------------------------+------------+----------+----------- - color_check | c | {color} | - | (color > 0) | f | f | t - constraint_6 | c | {time} | - | (("time" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND ("time" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone)) | f | f | t -(2 rows) - -ALTER TABLE disttable DROP CONSTRAINT color_check; -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------+------+---------+-------+------+------------+----------+----------- -(0 rows) - -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated ---------------+------+---------+-------+------------------------------------------------------------------------------------------------------------------------------------------------+------------+----------+----------- - constraint_6 | c | {time} | - | (("time" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND ("time" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone)) | f | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT show_chunks('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: -SELECT show_chunks('disttable') -NOTICE: [db_dist_ddl_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_17_6_chunk -(1 row) - - -NOTICE: [db_dist_ddl_1]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_1]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_1]: -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk -NOTICE: [db_dist_ddl_1]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated -------------+----+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+----------+--------+--------- -constraint_6|c |{time} |- |(("time" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND ("time" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT show_chunks('disttable') -NOTICE: [db_dist_ddl_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_17_6_chunk -(1 row) - - -NOTICE: [db_dist_ddl_2]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_2]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_2]: -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk -NOTICE: [db_dist_ddl_2]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated -------------+----+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+----------+--------+--------- -constraint_6|c |{time} |- |(("time" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND ("time" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))|f |f |t -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT show_chunks('disttable') -NOTICE: [db_dist_ddl_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_17_6_chunk -(1 row) - - -NOTICE: [db_dist_ddl_3]: -SELECT * FROM test.show_constraints('disttable') -NOTICE: [db_dist_ddl_3]: -Constraint|Type|Columns|Index|Expr|Deferrable|Deferred|Validated -----------+----+-------+-----+----+----------+--------+--------- -(0 rows) - - -NOTICE: [db_dist_ddl_3]: -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk -NOTICE: [db_dist_ddl_3]: -Constraint |Type|Columns|Index|Expr |Deferrable|Deferred|Validated -------------+----+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+----------+--------+--------- -constraint_6|c |{time} |- |(("time" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND ("time" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))|f |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable; --- Test event triggers behaviour -CREATE OR REPLACE FUNCTION test_event_trigger_sql_drop_function() RETURNS event_trigger -LANGUAGE plpgsql AS $$ -BEGIN - EXECUTE 'DROP TABLE IF EXISTS unexist_table'; -END -$$; -\c :TEST_DBNAME :ROLE_SUPERUSER; -CREATE EVENT TRIGGER test_event_trigger_sqldrop ON sql_drop - WHEN TAG IN ('drop table') - EXECUTE FUNCTION test_event_trigger_sql_drop_function(); -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Test DROP inside event trigger on local table (should not crash) -CREATE TABLE non_htable (id int PRIMARY KEY); -DROP TABLE non_htable; -NOTICE: table "unexist_table" does not exist, skipping -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP EVENT TRIGGER test_event_trigger_sqldrop; -SET ROLE :ROLE_1; --- Test DDL blocking from non-frontend session --- --- We test only special corner cases since most of this functionality already --- been tested before. --- -CREATE TABLE disttable(time timestamptz, device int); -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => 3); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 18 | public | disttable | t -(1 row) - -CREATE INDEX disttable_device_idx ON disttable (device); --- Test alter replication factor on empty table -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - replication_factor --------------------- - 3 -(1 row) - -SELECT * FROM set_replication_factor('disttable', 1); - set_replication_factor ------------------------- - -(1 row) - -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - replication_factor --------------------- - 1 -(1 row) - -SELECT * FROM set_replication_factor('disttable', 1); - set_replication_factor ------------------------- - -(1 row) - -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - replication_factor --------------------- - 1 -(1 row) - -SELECT * FROM set_replication_factor('disttable', 2); - set_replication_factor ------------------------- - -(1 row) - -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - replication_factor --------------------- - 2 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('disttable', 4); -ERROR: replication factor too large for hypertable "disttable" -SELECT * FROM set_replication_factor('disttable', 0); -ERROR: invalid replication factor -SELECT * FROM set_replication_factor('disttable', NULL); -ERROR: invalid replication factor -\set ON_ERROR_STOP 1 -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - replication_factor --------------------- - 2 -(1 row) - -\c :DATA_NODE_1 -SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'disttable'; - schemaname | tablename -------------+----------- - public | disttable -(1 row) - -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace -----------------------+----------+------+--------+---------+-----------+------------ - disttable_device_idx | {device} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(2 rows) - -\set ON_ERROR_STOP 0 --- fail to alter replication factor for the table on data node -SELECT * FROM set_replication_factor('disttable', 1); -ERROR: hypertable "disttable" is not distributed --- Test TRUNCATE blocked on data node -TRUNCATE disttable; -ERROR: operation is blocked on a distributed hypertable member --- Test ALTER by non-frontend session -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); -ERROR: operation is blocked on a distributed hypertable member --- Test path for delayed relid resolving -ALTER TABLE disttable RENAME TO disttable2; -ERROR: operation is blocked on a distributed hypertable member --- Test for hypertables collected during drop -DROP INDEX disttable_device_idx; -ERROR: operation is blocked on a distributed hypertable member -DROP TABLE disttable; -ERROR: operation is blocked on a distributed hypertable member -\set ON_ERROR_STOP 1 --- Explicitly allow execution -SET timescaledb.enable_client_ddl_on_data_nodes TO true; -DROP INDEX disttable_device_idx; -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ---------------------+---------+------+--------+---------+-----------+------------ - disttable_time_idx | {time} | | f | f | f | -(1 row) - -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; --- Should fail because of the inconsistency -\set ON_ERROR_STOP 0 -DROP INDEX disttable_device_idx; -ERROR: [db_dist_ddl_1]: index "disttable_device_idx" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE disttable; --- Ensure VACUUM/ANALYZE commands can be run on a data node --- without enabling timescaledb.enable_client_ddl_on_data_nodes guc -CREATE TABLE disttable(time timestamptz NOT NULL, device int); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 19 | public | disttable | t -(1 row) - -\c :DATA_NODE_1 -ANALYZE disttable; -ANALYZE; -VACUUM disttable; -VACUUM; -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP TABLE disttable; --- Ensure ANALYZE commands can be run on a set of data nodes --- --- Issue: #4508 --- -CREATE TABLE hyper(time TIMESTAMPTZ, device INT, temp FLOAT); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 4, chunk_time_interval => interval '18 hours', replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (20,public,hyper,t) -(1 row) - -INSERT INTO hyper SELECT t, ceil((random() * 5))::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-05'::timestamptz, '1 minute') as t; -ANALYZE hyper; -DROP TABLE hyper; --- --- Ensure single query multi-statement command is blocked --- --- Issue #4818 --- -CREATE TABLE disttable(time timestamptz NOT NULL, device int); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 21 | public | disttable | t -(1 row) - -CREATE OR REPLACE PROCEDURE test_dist_multi_stmt_command() -LANGUAGE plpgsql AS $$ -BEGIN - EXECUTE 'ANALYZE disttable; ANALYZE disttable'; -END -$$; -SET timescaledb.hide_data_node_name_in_errors = 'on'; --- unsupported -\set ON_ERROR_STOP 0 -CALL test_dist_multi_stmt_command(); -ERROR: nested commands are not supported on distributed hypertable -\set ON_ERROR_STOP 1 -DROP TABLE disttable; --- --- Test hypertable distributed defaults --- -SHOW timescaledb.hypertable_distributed_default; - timescaledb.hypertable_distributed_default --------------------------------------------- - auto -(1 row) - -SHOW timescaledb.hypertable_replication_factor_default; - timescaledb.hypertable_replication_factor_default ---------------------------------------------------- - 1 -(1 row) - -/* CASE1: create_hypertable(distributed, replication_factor) */ --- defaults are not applied -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -\set ON_ERROR_STOP 0 -SELECT create_hypertable('drf_test', 'time', distributed=>false, replication_factor=>1); -ERROR: local hypertables cannot set replication_factor -\set ON_ERROR_STOP 1 -SELECT create_hypertable('drf_test', 'time', distributed=>true, replication_factor=>1); - create_hypertable ------------------------- - (22,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 1 -(1 row) - -DROP TABLE drf_test; -/* CASE2: create_hypertable(distributed) */ --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; --- create regular hypertable by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); - create_hypertable ------------------------- - (23,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - f | -(1 row) - -DROP TABLE drf_test; --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); - create_hypertable ------------------------- - (24,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 1 -(1 row) - -DROP TABLE drf_test; --- distributed (same as auto) -SET timescaledb.hypertable_distributed_default TO 'distributed'; --- create regular hypertable by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); - create_hypertable ------------------------- - (25,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - f | -(1 row) - -DROP TABLE drf_test; --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); - create_hypertable ------------------------- - (26,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 1 -(1 row) - -DROP TABLE drf_test; --- local -SET timescaledb.hypertable_distributed_default TO 'local'; --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); -ERROR: local hypertables cannot set replication_factor -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); - create_hypertable ------------------------- - (27,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 1 -(1 row) - -DROP TABLE drf_test; -/* CASE3: create_hypertable(replication_factor) */ --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; --- create distributed hypertable when replication_factor > 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); - create_hypertable ------------------------- - (28,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 2 -(1 row) - -DROP TABLE drf_test; --- distributed -SET timescaledb.hypertable_distributed_default TO 'distributed'; --- create distributed hypertable -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); - create_hypertable ------------------------- - (29,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 2 -(1 row) - -DROP TABLE drf_test; --- local -SET timescaledb.hypertable_distributed_default TO 'local'; --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); -ERROR: local hypertables cannot set replication_factor -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 --- distributed hypertable member: replication_factor=>-1 -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=> -1); -ERROR: local hypertables cannot set replication_factor -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 -/* CASE4: create_hypertable() */ --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; --- regular by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); - create_hypertable ------------------------- - (30,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - f | -(1 row) - -DROP TABLE drf_test; --- distributed -SET timescaledb.hypertable_distributed_default TO 'distributed'; --- distributed hypertable with using default replication factor -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); - create_hypertable ------------------------- - (31,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 1 -(1 row) - -DROP TABLE drf_test; --- local -SET timescaledb.hypertable_distributed_default TO 'distributed'; --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); - create_hypertable ------------------------- - (32,public,drf_test,t) -(1 row) - -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 -/* CASE5: create_distributed_hypertable() default replication factor */ -SET timescaledb.hypertable_distributed_default TO 'auto'; -SET timescaledb.hypertable_replication_factor_default TO 3; -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_distributed_hypertable('drf_test', 'time'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (33,public,drf_test,t) -(1 row) - -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; - is_distributed | replication_factor -----------------+-------------------- - t | 3 -(1 row) - -DROP TABLE drf_test; --- test drop_stale_chunks() --- --- test directly on a data node first -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (34,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_34_31_chunk - _timescaledb_internal._dist_hyper_34_32_chunk - _timescaledb_internal._dist_hyper_34_33_chunk - _timescaledb_internal._dist_hyper_34_34_chunk - _timescaledb_internal._dist_hyper_34_35_chunk -(5 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_34_31_chunk -_timescaledb_internal._dist_hyper_34_32_chunk -_timescaledb_internal._dist_hyper_34_33_chunk -_timescaledb_internal._dist_hyper_34_34_chunk -_timescaledb_internal._dist_hyper_34_35_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_34_31_chunk -_timescaledb_internal._dist_hyper_34_32_chunk -_timescaledb_internal._dist_hyper_34_33_chunk -_timescaledb_internal._dist_hyper_34_34_chunk -_timescaledb_internal._dist_hyper_34_35_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_34_31_chunk -_timescaledb_internal._dist_hyper_34_32_chunk -_timescaledb_internal._dist_hyper_34_33_chunk -_timescaledb_internal._dist_hyper_34_34_chunk -_timescaledb_internal._dist_hyper_34_35_chunk -(5 rows) - - - remote_exec -------------- - -(1 row) - -\c :DATA_NODE_1 --- check call arguments when executed on data node -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.drop_stale_chunks(NULL, NULL); -ERROR: chunks argument cannot be NULL -SELECT _timescaledb_functions.drop_stale_chunks('dn1', NULL); -ERROR: node_name argument cannot be used on the data node -\set ON_ERROR_STOP 1 --- direct call to all chunks other then 19, 21 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 19 | _dist_hyper_34_31_chunk - 20 | _dist_hyper_34_32_chunk - 21 | _dist_hyper_34_33_chunk - 22 | _dist_hyper_34_34_chunk - 23 | _dist_hyper_34_35_chunk -(5 rows) - -SET client_min_messages TO DEBUG1; -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19, 21]::integer[]); -LOG: statement: SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19, 21]::integer[]); -DEBUG: dropping chunk _timescaledb_internal._dist_hyper_34_32_chunk -DEBUG: dropping chunk _timescaledb_internal._dist_hyper_34_34_chunk -DEBUG: dropping chunk _timescaledb_internal._dist_hyper_34_35_chunk - drop_stale_chunks -------------------- - -(1 row) - -RESET client_min_messages; -LOG: statement: RESET client_min_messages; -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 19 | _dist_hyper_34_31_chunk - 21 | _dist_hyper_34_33_chunk -(2 rows) - --- ensure that drop_stale_chunks() does not affect local chunks -CREATE TABLE local_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_hypertable('local_test', 'time', 'device', 3); - create_hypertable --------------------------- - (31,public,local_test,t) -(1 row) - -INSERT INTO local_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('local_test'); - show_chunks ------------------------------------------- - _timescaledb_internal._hyper_31_24_chunk - _timescaledb_internal._hyper_31_25_chunk - _timescaledb_internal._hyper_31_26_chunk - _timescaledb_internal._hyper_31_27_chunk - _timescaledb_internal._hyper_31_28_chunk -(5 rows) - -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 19 | _dist_hyper_34_31_chunk - 21 | _dist_hyper_34_33_chunk - 24 | _hyper_31_24_chunk - 25 | _hyper_31_25_chunk - 26 | _hyper_31_26_chunk - 27 | _hyper_31_27_chunk - 28 | _hyper_31_28_chunk -(7 rows) - -SET client_min_messages TO DEBUG1; -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19]::integer[]); -LOG: statement: SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19]::integer[]); -DEBUG: dropping chunk _timescaledb_internal._dist_hyper_34_33_chunk - drop_stale_chunks -------------------- - -(1 row) - -RESET client_min_messages; -LOG: statement: RESET client_min_messages; -SELECT * from show_chunks('local_test'); - show_chunks ------------------------------------------- - _timescaledb_internal._hyper_31_24_chunk - _timescaledb_internal._hyper_31_25_chunk - _timescaledb_internal._hyper_31_26_chunk - _timescaledb_internal._hyper_31_27_chunk - _timescaledb_internal._hyper_31_28_chunk -(5 rows) - -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 19 | _dist_hyper_34_31_chunk - 24 | _hyper_31_24_chunk - 25 | _hyper_31_25_chunk - 26 | _hyper_31_26_chunk - 27 | _hyper_31_27_chunk - 28 | _hyper_31_28_chunk -(6 rows) - -DROP TABLE local_test; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP TABLE dist_test; --- test from access node -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (35,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_36_chunk - _timescaledb_internal._dist_hyper_35_37_chunk - _timescaledb_internal._dist_hyper_35_38_chunk - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - - remote_exec -------------- - -(1 row) - --- check call arguments when executed on access node -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.drop_stale_chunks( NULL, NULL); -ERROR: node_name argument cannot be NULL -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[1,2,3]); -ERROR: node_name argument cannot be NULL -\set ON_ERROR_STOP 1 --- create stale chunk by dropping them from access node -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_36_chunk; -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_37_chunk; -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_38_chunk - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_36_chunk -_timescaledb_internal._dist_hyper_35_37_chunk -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(5 rows) - - - remote_exec -------------- - -(1 row) - ----- drop stale chunks 36, 37 on data nodes -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_1'); - drop_stale_chunks -------------------- - -(1 row) - -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_2'); - drop_stale_chunks -------------------- - -(1 row) - -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_3'); - drop_stale_chunks -------------------- - -(1 row) - -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_38_chunk - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - --- test drop_stale_chunks() with compressed chunk -ALTER TABLE dist_test set (timescaledb.compress, timescaledb.compress_segmentby = 'device', timescaledb.compress_orderby = 'time'); -SELECT compress_chunk('_timescaledb_internal._dist_hyper_35_38_chunk'); - compress_chunk ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_38_chunk -(1 row) - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+---------------------------- - 31 | _dist_hyper_35_38_chunk - 32 | _dist_hyper_35_39_chunk - 33 | _dist_hyper_35_40_chunk - 34 | compress_hyper_33_34_chunk -(4 rows) - -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_38_chunk - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_38_chunk; -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(2 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_35_38_chunk -_timescaledb_internal._dist_hyper_35_39_chunk -_timescaledb_internal._dist_hyper_35_40_chunk -(3 rows) - - - remote_exec -------------- - -(1 row) - --- drop stale chunk 38 -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_1'); - drop_stale_chunks -------------------- - -(1 row) - -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_2'); - drop_stale_chunks -------------------- - -(1 row) - -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_3'); - drop_stale_chunks -------------------- - -(1 row) - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 32 | _dist_hyper_35_39_chunk - 33 | _dist_hyper_35_40_chunk -(2 rows) - -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_35_39_chunk - _timescaledb_internal._dist_hyper_35_40_chunk -(2 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP TABLE dist_test; --- test alter_data_node() auto drop stale chunks on available --- -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (36,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_36_41_chunk - _timescaledb_internal._dist_hyper_36_42_chunk - _timescaledb_internal._dist_hyper_36_43_chunk - _timescaledb_internal._dist_hyper_36_44_chunk - _timescaledb_internal._dist_hyper_36_45_chunk -(5 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_ddl_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_1]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_36_41_chunk -_timescaledb_internal._dist_hyper_36_42_chunk -_timescaledb_internal._dist_hyper_36_43_chunk -_timescaledb_internal._dist_hyper_36_44_chunk -_timescaledb_internal._dist_hyper_36_45_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_2]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_36_41_chunk -_timescaledb_internal._dist_hyper_36_42_chunk -_timescaledb_internal._dist_hyper_36_43_chunk -_timescaledb_internal._dist_hyper_36_44_chunk -_timescaledb_internal._dist_hyper_36_45_chunk -(5 rows) - - -NOTICE: [db_dist_ddl_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_ddl_3]: -show_chunks ---------------------------------------------- -_timescaledb_internal._dist_hyper_36_41_chunk -_timescaledb_internal._dist_hyper_36_42_chunk -_timescaledb_internal._dist_hyper_36_43_chunk -_timescaledb_internal._dist_hyper_36_44_chunk -_timescaledb_internal._dist_hyper_36_45_chunk -(5 rows) - - - remote_exec -------------- - -(1 row) - -SELECT alter_data_node(:'DATA_NODE_1', available => false); -WARNING: altering data node is deprecated - alter_data_node -------------------------------------------------- - (db_dist_ddl_1,localhost,55432,db_dist_ddl_1,f) -(1 row) - --- create stale chunks -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_36_41_chunk; -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_36_42_chunk; -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 35 | _dist_hyper_36_41_chunk - 36 | _dist_hyper_36_42_chunk - 37 | _dist_hyper_36_43_chunk - 38 | _dist_hyper_36_44_chunk - 39 | _dist_hyper_36_45_chunk -(5 rows) - -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_36_41_chunk - _timescaledb_internal._dist_hyper_36_42_chunk - _timescaledb_internal._dist_hyper_36_43_chunk - _timescaledb_internal._dist_hyper_36_44_chunk - _timescaledb_internal._dist_hyper_36_45_chunk -(5 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- drop stale chunks by making data node available -SELECT alter_data_node(:'DATA_NODE_1', available => true); -WARNING: altering data node is deprecated - alter_data_node -------------------------------------------------- - (db_dist_ddl_1,localhost,55432,db_dist_ddl_1,t) -(1 row) - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - id | table_name -----+------------------------- - 37 | _dist_hyper_36_43_chunk - 38 | _dist_hyper_36_44_chunk - 39 | _dist_hyper_36_45_chunk -(3 rows) - -SELECT * from show_chunks('dist_test'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_36_43_chunk - _timescaledb_internal._dist_hyper_36_44_chunk - _timescaledb_internal._dist_hyper_36_45_chunk -(3 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP TABLE dist_test; --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_grant-13.out b/tsl/test/expected/dist_grant-13.out deleted file mode 100644 index 62ca1d83cf5..00000000000 --- a/tsl/test/expected/dist_grant-13.out +++ /dev/null @@ -1,1308 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_grant_1 | db_dist_grant_1 | t | t | t - db_dist_grant_2 | db_dist_grant_2 | t | t | t - db_dist_grant_3 | db_dist_grant_3 | t | t | t -(3 rows) - -CREATE TABLE conditions(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -GRANT SELECT ON conditions TO :ROLE_1; -GRANT INSERT, DELETE ON conditions TO :ROLE_2; -SELECT relname, relacl FROM pg_class WHERE relname = 'conditions'; - relname | relacl -------------+-------------------------------------------------------------------------------------------------------------------- - conditions | {cluster_super_user=arwdDxt/cluster_super_user,test_role_1=r/cluster_super_user,test_role_2=ad/cluster_super_user} -(1 row) - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | conditions | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - f | t | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - - remote_exec -------------- - -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; --- Check that we can actually execute a select as non-owner -SET ROLE :ROLE_1; -SELECT COUNT(*) FROM conditions; - count -------- - 44641 -(1 row) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -GRANT UPDATE ON conditions TO :ROLE_2; -BEGIN; -GRANT TRUNCATE ON conditions TO :ROLE_2; -ROLLBACK; --- Should have UPDATE, but not TRUNCATE -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege(:'ROLE_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege(:'ROLE_2', 'conditions', 'TRUNCATE') AS "TRUNCATE"; - SELECT | DELETE | INSERT | UPDATE | TRUNCATE ---------+--------+--------+--------+---------- - f | t | t | t | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Add another data node and check that grants are propagated when the --- data node is attached to an existing table. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------+-----------------+--------------+------------------+------------------- - data4 | db_dist_grant_4 | t | t | t -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -ERROR: [data4]: relation "conditions" does not exist -\set ON_ERROR_STOP 1 -SELECT * FROM attach_data_node('data4', 'conditions'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "device" was increased to 4 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+----------- - 1 | 1 | data4 -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-02-01 00:00:00'::timestamptz, '2019-03-01 00:00:00', '1 min') AS time; -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [data4]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that grants are not propagated when enable_grant_propagation --- is false. -SET timescaledb.enable_grant_propagation = false; -CREATE TABLE no_grants(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT); -GRANT SELECT ON no_grants TO :ROLE_1; --- First case is when table is created. Grants should not be propagated. -SELECT * FROM create_distributed_hypertable('no_grants', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | no_grants | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Second case is when grants is done on an existing table. The grant --- should not be propagated. -GRANT INSERT ON no_grants TO :ROLE_1; -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE conditions; -DROP TABLE no_grants; --- Check that grants and revokes are copied properly to the chunks and --- that newly created chunks have the right privileges. -CREATE TABLE conditions( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a hypertable and show that it does not have any privileges -SELECT * FROM create_hypertable('conditions', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 3 | public | conditions | t -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-------------------+-------------------+---------- - public | conditions | table | | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | | | - _timescaledb_internal | _hyper_3_36_chunk | table | | | - _timescaledb_internal | _hyper_3_37_chunk | table | | | -(3 rows) - --- Add privileges and show that they propagate to the chunks -GRANT SELECT, INSERT ON conditions TO PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(3 rows) - --- Create some more chunks and show that they also get the privileges. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-10 00:00'::timestamp, '2018-12-20 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(5 rows) - --- Revoke one of the privileges and show that it propagate to the --- chunks. -REVOKE INSERT ON conditions FROM PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(5 rows) - --- Add some more chunks and show that it inherits the grants from the --- hypertable. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-20 00:00'::timestamp, '2018-12-30 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_40_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_41_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(7 rows) - --- Change grants of one chunk explicitly and check that it is possible -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -GRANT UPDATE ON _timescaledb_internal._hyper_3_35_chunk TO PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =rw/cluster_super_user | | -(1 row) - -REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =w/cluster_super_user | | -(1 row) - -DROP TABLE conditions; --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE conditions( - time timestamptz, - device int CHECK (device > 0), - temp float, - PRIMARY KEY (time,device) -); -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 4 | public | conditions | t -(1 row) - --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -\set ON_ERROR_STOP 0 -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -ERROR: permission denied for table conditions -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - --- Check that GRANT ALL IN SCHEMA adds privileges to the parent --- and also does so on the foreign chunks in another schema -CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; -CALL distributed_exec($$ CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; $$); -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(6 rows) - --- Check that REVOKE ALL IN SCHEMA removes privileges of the parent --- and also does so on foreign chunks in another schema -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(6 rows) - --- Create chunks in the same schema as the hypertable and check that --- they also get the same privileges as the hypertable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE measurements( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a distributed hypertable with chunks in the same schema -SELECT * FROM create_distributed_hypertable('public.measurements', 'time', chunk_time_interval => '5 days'::interval, associated_schema_name => 'public'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 5 | public | measurements | t -(1 row) - -INSERT INTO measurements -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- Create a local regular table -CREATE TABLE local(g int primary key, h int); --- Create a local hypertable -CREATE TABLE conditions_lht(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -SELECT * FROM create_hypertable('conditions_lht', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 6 | public | conditions_lht | t -(1 row) - -INSERT INTO conditions_lht -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- GRANT ALL and check privileges of these mix of local table, local hypertable and distributed hypertable -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(1 row) - --- REVOKE ALL and check privileges -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_4 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+------+------------------- -(0 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Test GRANT/REVOKE on DATABASE -SET client_min_messages TO DEBUG1; --- Test GRANT/REVOKE command being deparsed with the database name and --- being propagated to the data nodes -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT ALL ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT ALL ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT ALL ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT ALL ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER, :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user, default_perm_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user, default_perm_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user, default_perm_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER WITH GRANT OPTION; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user WITH GRANT OPTION; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user WITH GRANT OPTION -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user WITH GRANT OPTION -REVOKE TEMP ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE TEMP ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE temp ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE temp ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE temp ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE temp ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER CASCADE; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user CASCADE; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user CASCADE -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user CASCADE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER RESTRICT; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user RESTRICT; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user --- Grant to specific role types -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO PUBLIC; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO PUBLIC; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO PUBLIC -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO PUBLIC -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO PUBLIC -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO PUBLIC -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO CURRENT_USER; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO CURRENT_USER -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO CURRENT_USER -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO CURRENT_USER -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO CURRENT_USER -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO SESSION_USER, :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO SESSION_USER, cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO SESSION_USER, cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO SESSION_USER, cluster_super_user --- PG14 added support for CURRENT_ROLE -\set ON_ERROR_STOP 0 -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_ROLE; -ERROR: syntax error at or near "CURRENT_ROLE" at character 52 -\set ON_ERROR_STOP 1 --- Grant on other database should not be propagated -GRANT CREATE ON DATABASE :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant_1 TO cluster_super_user; --- Prevent mixing databases -\set ON_ERROR_STOP 0 -GRANT CREATE ON DATABASE :TEST_DBNAME, :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant, db_dist_grant_1 TO cluster_super_user; -ERROR: cannot change privileges on multiple databases -\set ON_ERROR_STOP 1 --- Test disabling DDL commands on global objects -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'off'; --- ALTER DEFAULT PRIVELEGES -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -LOG: statement: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; -DEBUG: skipping dist DDL on object: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; --- GRANT/REVOKE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -REVOKE ALL ON SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON SCHEMA public FROM default_perm_user; -GRANT ALL ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON SCHEMA public TO default_perm_user; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -RESET client_min_messages; -LOG: statement: RESET client_min_messages; --- Test GRANT on foreign server and data node authentication using a --- user mapping -SET ROLE :ROLE_3; -SELECT current_user; - current_user --------------- - test_role_3 -(1 row) - -CREATE TABLE disttable_role_3(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- Can't create distributed hypertable without GRANTs on foreign servers (data nodes) -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_1 -\set ON_ERROR_STOP 1 --- Grant USAGE on DATA_NODE_1 (but it is not enough) -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_2 -\set ON_ERROR_STOP 1 --- Creating the hypertable should work with GRANTs on both servers. -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_2 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is no password in the passfile and --- no user mapping. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_1" -\set ON_ERROR_STOP 1 -RESET ROLE; -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1 OPTIONS (user :'ROLE_3', password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is only a user mapping for data --- node DATA_NODE_1. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_2" -\set ON_ERROR_STOP 1 -RESET ROLE; --- Create user mapping for ROLE_3, but don't specify user in --- options. The "current user" will instead be used when connecting. -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2 OPTIONS (password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; --- User should be able to connect and create the distributed --- hypertable at this point. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------------+--------- - 9 | public | disttable_role_3 | t -(1 row) - --- Test insert and query -INSERT INTO disttable_role_3 VALUES ('2019-01-01 00:00:00', 1, 23.4); -SELECT * FROM disttable_role_3; - time | device | temp -------------------------------+--------+------ - Tue Jan 01 00:00:00 2019 PST | 1 | 23.4 -(1 row) - -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1; -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2; --- Test altering default privileges -RESET ROLE; --- Should be superuser -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -CALL distributed_exec($$ CREATE TABLE nodefprivs (time timestamptz, value int) $$); -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Should fail due to lack of privileges (only insert on one data node --- to make error reporting deterministic) -CALL distributed_exec($$ INSERT INTO nodefprivs VALUES ('2019-01-01 00:00:00', 1) $$, ARRAY[:'DATA_NODE_1']); -ERROR: [db_dist_grant_1]: permission denied for table nodefprivs -\set ON_ERROR_STOP 1 --- Reset to super user -RESET ROLE; --- Now alter default privileges and create table -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole |defaclobjtype|defaclacl -------------------+-------------+-------------------------------------------------------------------------------- -cluster_super_user|r |{cluster_super_user=arwdDxt/cluster_super_user,test_role_1=a/cluster_super_user} -(1 row) - - --- -(1 row) - -CALL distributed_exec($$ CREATE TABLE defprivs (time timestamptz, value int) $$); --- Switch to the role that was granted default privileges -SET ROLE :ROLE_1; --- Should succeed since user will have insert privileges by default -CALL distributed_exec($$ INSERT INTO defprivs VALUES ('2019-01-01 00:00:00', 1) $$); -RESET ROLE; -ALTER DEFAULT PRIVILEGES REVOKE INSERT ON TABLES FROM :ROLE_1; --- No default privileges remain -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole|defaclobjtype|defaclacl -----------+-------------+--------- -(0 rows) - - --- -(1 row) - -CALL distributed_exec($$ DROP TABLE defprivs $$); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); -DROP DATABASE :DATA_NODE_4 WITH (FORCE); diff --git a/tsl/test/expected/dist_grant-14.out b/tsl/test/expected/dist_grant-14.out deleted file mode 100644 index 7f80b8dcb8f..00000000000 --- a/tsl/test/expected/dist_grant-14.out +++ /dev/null @@ -1,1312 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_grant_1 | db_dist_grant_1 | t | t | t - db_dist_grant_2 | db_dist_grant_2 | t | t | t - db_dist_grant_3 | db_dist_grant_3 | t | t | t -(3 rows) - -CREATE TABLE conditions(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -GRANT SELECT ON conditions TO :ROLE_1; -GRANT INSERT, DELETE ON conditions TO :ROLE_2; -SELECT relname, relacl FROM pg_class WHERE relname = 'conditions'; - relname | relacl -------------+-------------------------------------------------------------------------------------------------------------------- - conditions | {cluster_super_user=arwdDxt/cluster_super_user,test_role_1=r/cluster_super_user,test_role_2=ad/cluster_super_user} -(1 row) - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | conditions | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - f | t | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - - remote_exec -------------- - -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; --- Check that we can actually execute a select as non-owner -SET ROLE :ROLE_1; -SELECT COUNT(*) FROM conditions; - count -------- - 44641 -(1 row) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -GRANT UPDATE ON conditions TO :ROLE_2; -BEGIN; -GRANT TRUNCATE ON conditions TO :ROLE_2; -ROLLBACK; --- Should have UPDATE, but not TRUNCATE -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege(:'ROLE_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege(:'ROLE_2', 'conditions', 'TRUNCATE') AS "TRUNCATE"; - SELECT | DELETE | INSERT | UPDATE | TRUNCATE ---------+--------+--------+--------+---------- - f | t | t | t | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Add another data node and check that grants are propagated when the --- data node is attached to an existing table. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------+-----------------+--------------+------------------+------------------- - data4 | db_dist_grant_4 | t | t | t -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -ERROR: [data4]: relation "conditions" does not exist -\set ON_ERROR_STOP 1 -SELECT * FROM attach_data_node('data4', 'conditions'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "device" was increased to 4 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+----------- - 1 | 1 | data4 -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-02-01 00:00:00'::timestamptz, '2019-03-01 00:00:00', '1 min') AS time; -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [data4]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that grants are not propagated when enable_grant_propagation --- is false. -SET timescaledb.enable_grant_propagation = false; -CREATE TABLE no_grants(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT); -GRANT SELECT ON no_grants TO :ROLE_1; --- First case is when table is created. Grants should not be propagated. -SELECT * FROM create_distributed_hypertable('no_grants', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | no_grants | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Second case is when grants is done on an existing table. The grant --- should not be propagated. -GRANT INSERT ON no_grants TO :ROLE_1; -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE conditions; -DROP TABLE no_grants; --- Check that grants and revokes are copied properly to the chunks and --- that newly created chunks have the right privileges. -CREATE TABLE conditions( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a hypertable and show that it does not have any privileges -SELECT * FROM create_hypertable('conditions', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 3 | public | conditions | t -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-------------------+-------------------+---------- - public | conditions | table | | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | | | - _timescaledb_internal | _hyper_3_36_chunk | table | | | - _timescaledb_internal | _hyper_3_37_chunk | table | | | -(3 rows) - --- Add privileges and show that they propagate to the chunks -GRANT SELECT, INSERT ON conditions TO PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(3 rows) - --- Create some more chunks and show that they also get the privileges. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-10 00:00'::timestamp, '2018-12-20 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(5 rows) - --- Revoke one of the privileges and show that it propagate to the --- chunks. -REVOKE INSERT ON conditions FROM PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(5 rows) - --- Add some more chunks and show that it inherits the grants from the --- hypertable. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-20 00:00'::timestamp, '2018-12-30 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_40_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_41_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(7 rows) - --- Change grants of one chunk explicitly and check that it is possible -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -GRANT UPDATE ON _timescaledb_internal._hyper_3_35_chunk TO PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =rw/cluster_super_user | | -(1 row) - -REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =w/cluster_super_user | | -(1 row) - -DROP TABLE conditions; --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE conditions( - time timestamptz, - device int CHECK (device > 0), - temp float, - PRIMARY KEY (time,device) -); -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 4 | public | conditions | t -(1 row) - --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -\set ON_ERROR_STOP 0 -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -ERROR: permission denied for table conditions -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - --- Check that GRANT ALL IN SCHEMA adds privileges to the parent --- and also does so on the foreign chunks in another schema -CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; -CALL distributed_exec($$ CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; $$); -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(6 rows) - --- Check that REVOKE ALL IN SCHEMA removes privileges of the parent --- and also does so on foreign chunks in another schema -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(6 rows) - --- Create chunks in the same schema as the hypertable and check that --- they also get the same privileges as the hypertable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE measurements( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a distributed hypertable with chunks in the same schema -SELECT * FROM create_distributed_hypertable('public.measurements', 'time', chunk_time_interval => '5 days'::interval, associated_schema_name => 'public'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 5 | public | measurements | t -(1 row) - -INSERT INTO measurements -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- Create a local regular table -CREATE TABLE local(g int primary key, h int); --- Create a local hypertable -CREATE TABLE conditions_lht(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -SELECT * FROM create_hypertable('conditions_lht', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 6 | public | conditions_lht | t -(1 row) - -INSERT INTO conditions_lht -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- GRANT ALL and check privileges of these mix of local table, local hypertable and distributed hypertable -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(1 row) - --- REVOKE ALL and check privileges -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_4 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+------+------------------- -(0 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Test GRANT/REVOKE on DATABASE -SET client_min_messages TO DEBUG1; --- Test GRANT/REVOKE command being deparsed with the database name and --- being propagated to the data nodes -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT ALL ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT ALL ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT ALL ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT ALL ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER, :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user, default_perm_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user, default_perm_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user, default_perm_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER WITH GRANT OPTION; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user WITH GRANT OPTION; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user WITH GRANT OPTION -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user WITH GRANT OPTION -REVOKE TEMP ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE TEMP ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE temp ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE temp ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE temp ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE temp ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER CASCADE; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user CASCADE; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user CASCADE -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user CASCADE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER RESTRICT; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user RESTRICT; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user --- Grant to specific role types -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO PUBLIC; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO PUBLIC; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO PUBLIC -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO PUBLIC -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO PUBLIC -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO PUBLIC -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO CURRENT_USER; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO CURRENT_USER -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO CURRENT_USER -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO CURRENT_USER -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO CURRENT_USER -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO SESSION_USER, :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO SESSION_USER, cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO SESSION_USER, cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO SESSION_USER, cluster_super_user --- PG14 added support for CURRENT_ROLE -\set ON_ERROR_STOP 0 -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_ROLE; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO CURRENT_ROLE; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO CURRENT_ROLE -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO CURRENT_ROLE -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO CURRENT_ROLE -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO CURRENT_ROLE -\set ON_ERROR_STOP 1 --- Grant on other database should not be propagated -GRANT CREATE ON DATABASE :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant_1 TO cluster_super_user; --- Prevent mixing databases -\set ON_ERROR_STOP 0 -GRANT CREATE ON DATABASE :TEST_DBNAME, :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant, db_dist_grant_1 TO cluster_super_user; -ERROR: cannot change privileges on multiple databases -\set ON_ERROR_STOP 1 --- Test disabling DDL commands on global objects -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'off'; --- ALTER DEFAULT PRIVELEGES -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -LOG: statement: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; -DEBUG: skipping dist DDL on object: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; --- GRANT/REVOKE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -REVOKE ALL ON SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON SCHEMA public FROM default_perm_user; -GRANT ALL ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON SCHEMA public TO default_perm_user; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -RESET client_min_messages; -LOG: statement: RESET client_min_messages; --- Test GRANT on foreign server and data node authentication using a --- user mapping -SET ROLE :ROLE_3; -SELECT current_user; - current_user --------------- - test_role_3 -(1 row) - -CREATE TABLE disttable_role_3(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- Can't create distributed hypertable without GRANTs on foreign servers (data nodes) -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_1 -\set ON_ERROR_STOP 1 --- Grant USAGE on DATA_NODE_1 (but it is not enough) -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_2 -\set ON_ERROR_STOP 1 --- Creating the hypertable should work with GRANTs on both servers. -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_2 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is no password in the passfile and --- no user mapping. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_1" -\set ON_ERROR_STOP 1 -RESET ROLE; -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1 OPTIONS (user :'ROLE_3', password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is only a user mapping for data --- node DATA_NODE_1. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_2" -\set ON_ERROR_STOP 1 -RESET ROLE; --- Create user mapping for ROLE_3, but don't specify user in --- options. The "current user" will instead be used when connecting. -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2 OPTIONS (password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; --- User should be able to connect and create the distributed --- hypertable at this point. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------------+--------- - 9 | public | disttable_role_3 | t -(1 row) - --- Test insert and query -INSERT INTO disttable_role_3 VALUES ('2019-01-01 00:00:00', 1, 23.4); -SELECT * FROM disttable_role_3; - time | device | temp -------------------------------+--------+------ - Tue Jan 01 00:00:00 2019 PST | 1 | 23.4 -(1 row) - -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1; -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2; --- Test altering default privileges -RESET ROLE; --- Should be superuser -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -CALL distributed_exec($$ CREATE TABLE nodefprivs (time timestamptz, value int) $$); -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Should fail due to lack of privileges (only insert on one data node --- to make error reporting deterministic) -CALL distributed_exec($$ INSERT INTO nodefprivs VALUES ('2019-01-01 00:00:00', 1) $$, ARRAY[:'DATA_NODE_1']); -ERROR: [db_dist_grant_1]: permission denied for table nodefprivs -\set ON_ERROR_STOP 1 --- Reset to super user -RESET ROLE; --- Now alter default privileges and create table -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole |defaclobjtype|defaclacl -------------------+-------------+-------------------------------------------------------------------------------- -cluster_super_user|r |{cluster_super_user=arwdDxt/cluster_super_user,test_role_1=a/cluster_super_user} -(1 row) - - --- -(1 row) - -CALL distributed_exec($$ CREATE TABLE defprivs (time timestamptz, value int) $$); --- Switch to the role that was granted default privileges -SET ROLE :ROLE_1; --- Should succeed since user will have insert privileges by default -CALL distributed_exec($$ INSERT INTO defprivs VALUES ('2019-01-01 00:00:00', 1) $$); -RESET ROLE; -ALTER DEFAULT PRIVILEGES REVOKE INSERT ON TABLES FROM :ROLE_1; --- No default privileges remain -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole|defaclobjtype|defaclacl -----------+-------------+--------- -(0 rows) - - --- -(1 row) - -CALL distributed_exec($$ DROP TABLE defprivs $$); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); -DROP DATABASE :DATA_NODE_4 WITH (FORCE); diff --git a/tsl/test/expected/dist_grant-15.out b/tsl/test/expected/dist_grant-15.out deleted file mode 100644 index 7f80b8dcb8f..00000000000 --- a/tsl/test/expected/dist_grant-15.out +++ /dev/null @@ -1,1312 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_grant_1 | db_dist_grant_1 | t | t | t - db_dist_grant_2 | db_dist_grant_2 | t | t | t - db_dist_grant_3 | db_dist_grant_3 | t | t | t -(3 rows) - -CREATE TABLE conditions(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -GRANT SELECT ON conditions TO :ROLE_1; -GRANT INSERT, DELETE ON conditions TO :ROLE_2; -SELECT relname, relacl FROM pg_class WHERE relname = 'conditions'; - relname | relacl -------------+-------------------------------------------------------------------------------------------------------------------- - conditions | {cluster_super_user=arwdDxt/cluster_super_user,test_role_1=r/cluster_super_user,test_role_2=ad/cluster_super_user} -(1 row) - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | conditions | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - f | t | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -f |t |t -(1 row) - - - remote_exec -------------- - -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; --- Check that we can actually execute a select as non-owner -SET ROLE :ROLE_1; -SELECT COUNT(*) FROM conditions; - count -------- - 44641 -(1 row) - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -GRANT UPDATE ON conditions TO :ROLE_2; -BEGIN; -GRANT TRUNCATE ON conditions TO :ROLE_2; -ROLLBACK; --- Should have UPDATE, but not TRUNCATE -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege(:'ROLE_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege(:'ROLE_2', 'conditions', 'TRUNCATE') AS "TRUNCATE"; - SELECT | DELETE | INSERT | UPDATE | TRUNCATE ---------+--------+--------+--------+---------- - f | t | t | t | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Add another data node and check that grants are propagated when the --- data node is attached to an existing table. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------+-----------------+--------------+------------------+------------------- - data4 | db_dist_grant_4 | t | t | t -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -ERROR: [data4]: relation "conditions" does not exist -\set ON_ERROR_STOP 1 -SELECT * FROM attach_data_node('data4', 'conditions'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "device" was increased to 4 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+----------- - 1 | 1 | data4 -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-02-01 00:00:00'::timestamptz, '2019-03-01 00:00:00', '1 min') AS time; -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('test_role_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('test_role_2', 'conditions', 'TRUNCATE') AS "TRUNCATE" -NOTICE: [data4]: -SELECT|DELETE|INSERT|UPDATE|TRUNCATE -------+------+------+------+-------- -f |t |t |t |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that grants are not propagated when enable_grant_propagation --- is false. -SET timescaledb.enable_grant_propagation = false; -CREATE TABLE no_grants(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT); -GRANT SELECT ON no_grants TO :ROLE_1; --- First case is when table is created. Grants should not be propagated. -SELECT * FROM create_distributed_hypertable('no_grants', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | no_grants | t -(1 row) - -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | f -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |f -(1 row) - - - remote_exec -------------- - -(1 row) - --- Second case is when grants is done on an existing table. The grant --- should not be propagated. -GRANT INSERT ON no_grants TO :ROLE_1; -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; - SELECT | DELETE | INSERT ---------+--------+-------- - t | f | t -(1 row) - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_1]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_2]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_2]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [db_dist_grant_3]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [db_dist_grant_3]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - -NOTICE: [data4]: - SELECT has_table_privilege('test_role_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('test_role_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('test_role_1', 'no_grants', 'INSERT') AS "INSERT" -NOTICE: [data4]: -SELECT|DELETE|INSERT -------+------+------ -t |f |t -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE conditions; -DROP TABLE no_grants; --- Check that grants and revokes are copied properly to the chunks and --- that newly created chunks have the right privileges. -CREATE TABLE conditions( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a hypertable and show that it does not have any privileges -SELECT * FROM create_hypertable('conditions', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 3 | public | conditions | t -(1 row) - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-------------------+-------------------+---------- - public | conditions | table | | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | | | - _timescaledb_internal | _hyper_3_36_chunk | table | | | - _timescaledb_internal | _hyper_3_37_chunk | table | | | -(3 rows) - --- Add privileges and show that they propagate to the chunks -GRANT SELECT, INSERT ON conditions TO PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(3 rows) - --- Create some more chunks and show that they also get the privileges. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-10 00:00'::timestamp, '2018-12-20 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =ar/cluster_super_user | | -(5 rows) - --- Revoke one of the privileges and show that it propagate to the --- chunks. -REVOKE INSERT ON conditions FROM PUBLIC; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(5 rows) - --- Add some more chunks and show that it inherits the grants from the --- hypertable. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-20 00:00'::timestamp, '2018-12-30 00:00'::timestamp, '1h') AS time; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -\z _timescaledb_internal.*chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_36_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_37_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_38_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_39_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_40_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | - _timescaledb_internal | _hyper_3_41_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(7 rows) - --- Change grants of one chunk explicitly and check that it is possible -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =r/cluster_super_user | | -(1 row) - -GRANT UPDATE ON _timescaledb_internal._hyper_3_35_chunk TO PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =rw/cluster_super_user | | -(1 row) - -REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ------------------------+-------------------+-------+-----------------------------------------------+-------------------+---------- - _timescaledb_internal | _hyper_3_35_chunk | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | =w/cluster_super_user | | -(1 row) - -DROP TABLE conditions; --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE conditions( - time timestamptz, - device int CHECK (device > 0), - temp float, - PRIMARY KEY (time,device) -); -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 4 | public | conditions | t -(1 row) - --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -\set ON_ERROR_STOP 0 -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -ERROR: permission denied for table conditions -\set ON_ERROR_STOP 1 -RESET ROLE; -GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -RESET ROLE; -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - --- Check that GRANT ALL IN SCHEMA adds privileges to the parent --- and also does so on the foreign chunks in another schema -CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; -CALL distributed_exec($$ CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; $$); -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user + - | | default_perm_user=arwdDxt/cluster_super_user -(6 rows) - --- Check that REVOKE ALL IN SCHEMA removes privileges of the parent --- and also does so on foreign chunks in another schema -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(18 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1; - schema | name | access_privileges ------------------------+--------------+----------------------------------------------- - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user - _timescaledb_internal | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user_2=a/cluster_super_user -(6 rows) - --- Create chunks in the same schema as the hypertable and check that --- they also get the same privileges as the hypertable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE measurements( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); --- Create a distributed hypertable with chunks in the same schema -SELECT * FROM create_distributed_hypertable('public.measurements', 'time', chunk_time_interval => '5 days'::interval, associated_schema_name => 'public'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 5 | public | measurements | t -(1 row) - -INSERT INTO measurements -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- Create a local regular table -CREATE TABLE local(g int primary key, h int); --- Create a local hypertable -CREATE TABLE conditions_lht(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -SELECT * FROM create_hypertable('conditions_lht', 'time', chunk_time_interval => '5 days'::interval); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 6 | public | conditions_lht | t -(1 row) - -INSERT INTO conditions_lht -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; --- GRANT ALL and check privileges of these mix of local table, local hypertable and distributed hypertable -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user +| | - | | | default_perm_user=arwdDxt/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user+ - | | default_perm_user=arwdDxt/cluster_super_user -(1 row) - --- REVOKE ALL and check privileges -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+--------------+----------------------------------------------- - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user - public | _dist_hyper_ | cluster_super_user=arwdDxt/cluster_super_user -(3 rows) - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_4 :ROLE_CLUSTER_SUPERUSER; -\z measurements - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+--------------+-------+-----------------------------------------------+-------------------+---------- - public | measurements | table | cluster_super_user=arwdDxt/cluster_super_user | | -(1 row) - -\z conditions - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+------------+-------+-----------------------------------------------+-------------------+---------- - public | conditions | table | cluster_super_user=arwdDxt/cluster_super_user+| | - | | | default_perm_user_2=a/cluster_super_user | | -(1 row) - -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - schema | name | access_privileges ---------+------+------------------- -(0 rows) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- Test GRANT/REVOKE on DATABASE -SET client_min_messages TO DEBUG1; --- Test GRANT/REVOKE command being deparsed with the database name and --- being propagated to the data nodes -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT ALL ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT ALL ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT ALL ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT ALL ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER, :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO cluster_super_user, default_perm_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO cluster_super_user, default_perm_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO cluster_super_user, default_perm_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO cluster_super_user, default_perm_user -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER WITH GRANT OPTION; -LOG: statement: GRANT TEMP ON DATABASE db_dist_grant TO cluster_super_user WITH GRANT OPTION; -DEBUG: [db_dist_grant_1]: GRANT temp ON DATABASE db_dist_grant_1 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_2]: GRANT temp ON DATABASE db_dist_grant_2 TO cluster_super_user WITH GRANT OPTION -DEBUG: [db_dist_grant_3]: GRANT temp ON DATABASE db_dist_grant_3 TO cluster_super_user WITH GRANT OPTION -DEBUG: [data4]: GRANT temp ON DATABASE db_dist_grant_4 TO cluster_super_user WITH GRANT OPTION -REVOKE TEMP ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE TEMP ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE temp ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE temp ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE temp ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE temp ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER CASCADE; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user CASCADE; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user CASCADE -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user CASCADE -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user CASCADE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER RESTRICT; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user RESTRICT; -DEBUG: [db_dist_grant_1]: REVOKE ALL ON DATABASE db_dist_grant_1 FROM cluster_super_user -DEBUG: [db_dist_grant_2]: REVOKE ALL ON DATABASE db_dist_grant_2 FROM cluster_super_user -DEBUG: [db_dist_grant_3]: REVOKE ALL ON DATABASE db_dist_grant_3 FROM cluster_super_user -DEBUG: [data4]: REVOKE ALL ON DATABASE db_dist_grant_4 FROM cluster_super_user --- Grant to specific role types -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO PUBLIC; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO PUBLIC; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO PUBLIC -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO PUBLIC -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO PUBLIC -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO PUBLIC -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_USER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO CURRENT_USER; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO CURRENT_USER -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO CURRENT_USER -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO CURRENT_USER -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO CURRENT_USER -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO SESSION_USER, :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO SESSION_USER, cluster_super_user; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO SESSION_USER, cluster_super_user -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO SESSION_USER, cluster_super_user -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO SESSION_USER, cluster_super_user --- PG14 added support for CURRENT_ROLE -\set ON_ERROR_STOP 0 -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_ROLE; -LOG: statement: GRANT TEMP, TEMPORARY ON DATABASE db_dist_grant TO CURRENT_ROLE; -DEBUG: [db_dist_grant_1]: GRANT temp, temporary ON DATABASE db_dist_grant_1 TO CURRENT_ROLE -DEBUG: [db_dist_grant_2]: GRANT temp, temporary ON DATABASE db_dist_grant_2 TO CURRENT_ROLE -DEBUG: [db_dist_grant_3]: GRANT temp, temporary ON DATABASE db_dist_grant_3 TO CURRENT_ROLE -DEBUG: [data4]: GRANT temp, temporary ON DATABASE db_dist_grant_4 TO CURRENT_ROLE -\set ON_ERROR_STOP 1 --- Grant on other database should not be propagated -GRANT CREATE ON DATABASE :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant_1 TO cluster_super_user; --- Prevent mixing databases -\set ON_ERROR_STOP 0 -GRANT CREATE ON DATABASE :TEST_DBNAME, :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT CREATE ON DATABASE db_dist_grant, db_dist_grant_1 TO cluster_super_user; -ERROR: cannot change privileges on multiple databases -\set ON_ERROR_STOP 1 --- Test disabling DDL commands on global objects -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'off'; --- ALTER DEFAULT PRIVELEGES -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -LOG: statement: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; -DEBUG: skipping dist DDL on object: ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO test_role_1; --- GRANT/REVOKE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -LOG: statement: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON DATABASE db_dist_grant FROM cluster_super_user; -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -LOG: statement: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON DATABASE db_dist_grant TO cluster_super_user; -REVOKE ALL ON SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON SCHEMA public FROM default_perm_user; -GRANT ALL ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON SCHEMA public TO default_perm_user; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -LOG: statement: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -DEBUG: skipping dist DDL on object: REVOKE ALL ON ALL TABLES IN SCHEMA public FROM default_perm_user; -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -LOG: statement: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -DEBUG: skipping dist DDL on object: GRANT ALL ON ALL TABLES IN SCHEMA public TO default_perm_user; -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -LOG: statement: SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -RESET client_min_messages; -LOG: statement: RESET client_min_messages; --- Test GRANT on foreign server and data node authentication using a --- user mapping -SET ROLE :ROLE_3; -SELECT current_user; - current_user --------------- - test_role_3 -(1 row) - -CREATE TABLE disttable_role_3(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- Can't create distributed hypertable without GRANTs on foreign servers (data nodes) -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_1 -\set ON_ERROR_STOP 1 --- Grant USAGE on DATA_NODE_1 (but it is not enough) -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -ERROR: permission denied for foreign server db_dist_grant_2 -\set ON_ERROR_STOP 1 --- Creating the hypertable should work with GRANTs on both servers. -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_2 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is no password in the passfile and --- no user mapping. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_1" -\set ON_ERROR_STOP 1 -RESET ROLE; -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1 OPTIONS (user :'ROLE_3', password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; -\set ON_ERROR_STOP 0 --- Still cannot connect since there is only a user mapping for data --- node DATA_NODE_1. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" -ERROR: could not connect to "db_dist_grant_2" -\set ON_ERROR_STOP 1 -RESET ROLE; --- Create user mapping for ROLE_3, but don't specify user in --- options. The "current user" will instead be used when connecting. -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2 OPTIONS (password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; --- User should be able to connect and create the distributed --- hypertable at this point. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------------+--------- - 9 | public | disttable_role_3 | t -(1 row) - --- Test insert and query -INSERT INTO disttable_role_3 VALUES ('2019-01-01 00:00:00', 1, 23.4); -SELECT * FROM disttable_role_3; - time | device | temp -------------------------------+--------+------ - Tue Jan 01 00:00:00 2019 PST | 1 | 23.4 -(1 row) - -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1; -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2; --- Test altering default privileges -RESET ROLE; --- Should be superuser -SELECT current_user; - current_user --------------------- - cluster_super_user -(1 row) - -CALL distributed_exec($$ CREATE TABLE nodefprivs (time timestamptz, value int) $$); -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Should fail due to lack of privileges (only insert on one data node --- to make error reporting deterministic) -CALL distributed_exec($$ INSERT INTO nodefprivs VALUES ('2019-01-01 00:00:00', 1) $$, ARRAY[:'DATA_NODE_1']); -ERROR: [db_dist_grant_1]: permission denied for table nodefprivs -\set ON_ERROR_STOP 1 --- Reset to super user -RESET ROLE; --- Now alter default privileges and create table -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole |defaclobjtype|defaclacl -------------------+-------------+-------------------------------------------------------------------------------- -cluster_super_user|r |{cluster_super_user=arwdDxt/cluster_super_user,test_role_1=a/cluster_super_user} -(1 row) - - --- -(1 row) - -CALL distributed_exec($$ CREATE TABLE defprivs (time timestamptz, value int) $$); --- Switch to the role that was granted default privileges -SET ROLE :ROLE_1; --- Should succeed since user will have insert privileges by default -CALL distributed_exec($$ INSERT INTO defprivs VALUES ('2019-01-01 00:00:00', 1) $$); -RESET ROLE; -ALTER DEFAULT PRIVILEGES REVOKE INSERT ON TABLES FROM :ROLE_1; --- No default privileges remain -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_grant_1]: - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl - -NOTICE: [db_dist_grant_1]: -defaclrole|defaclobjtype|defaclacl -----------+-------------+--------- -(0 rows) - - --- -(1 row) - -CALL distributed_exec($$ DROP TABLE defprivs $$); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); -DROP DATABASE :DATA_NODE_4 WITH (FORCE); diff --git a/tsl/test/expected/dist_hypertable-13.out b/tsl/test/expected/dist_hypertable-13.out deleted file mode 100644 index 51d8eae846b..00000000000 --- a/tsl/test/expected/dist_hypertable-13.out +++ /dev/null @@ -1,6250 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_1 | db_dist_hypertable_1 | t | t | t - db_dist_hypertable_2 | db_dist_hypertable_2 | t | t | t - db_dist_hypertable_3 | db_dist_hypertable_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; --- Import testsupport.sql file to data nodes -\unset ECHO -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; ---Ensure INSERTs use DataNodeDispatch. DataNodeCopy is tested later -SET timescaledb.enable_distributed_insert_with_copy=false; --- Verify lack of tables -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -\set ON_ERROR_STOP 0 --- Test that one cannot directly create TimescaleDB foreign tables -CREATE FOREIGN TABLE foreign_table (time timestamptz, device int, temp float) SERVER :DATA_NODE_1; -ERROR: operation not supported -\set ON_ERROR_STOP 1 --- Create distributed hypertables. Add a trigger and primary key --- constraint to test how those work -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), color int, temp float, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 1); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - --- Increase the number of partitions. Expect warning since still too --- low. Dimension partitions should be updated to reflect new --- partitioning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} -(1 row) - -SELECT * FROM set_number_partitions('disttable', 2); -WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - --- Set number of partitions equal to the number of servers should not --- raise a warning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show the number of slices -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'disttable'; - table_name | column_name | num_slices -------------+-------------+------------ - disttable | device | 3 - disttable | time | -(2 rows) - --- This table tests both 1-dimensional tables and under-replication --- (replication_factor > num_data_nodes). -CREATE TABLE underreplicated(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- can't create an under-replicated hypertable -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -ERROR: replication factor too large for hypertable "underreplicated" -\set ON_ERROR_STOP 1 -RESET ROLE; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node(:'DATA_NODE_4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_4 | db_dist_hypertable_4 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_4 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 2 | public | underreplicated | t -(1 row) - --- test that attaching a data node to an existing hypertable with --- repartition=>false does not change the number of partitions when --- number of partitions is greater than number of data nodes. -SELECT * FROM set_number_partitions('disttable', 8, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - -SELECT attach_data_node(:'DATA_NODE_4', 'disttable', repartition => false); -WARNING: attaching data node is deprecated - attach_data_node ----------------------------- - (1,2,db_dist_hypertable_4) -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_4} - disttable | 2 | 1073741820 | {db_dist_hypertable_1} - disttable | 2 | 1342177275 | {db_dist_hypertable_2} - disttable | 2 | 1610612730 | {db_dist_hypertable_3} - disttable | 2 | 1879048185 | {db_dist_hypertable_4} -(8 rows) - ---create new session to clear out connections -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_4', force => true, drop_database => true, repartition => false); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "underreplicated" - delete_data_node ------------------- - t -(1 row) - -SET ROLE :ROLE_1; --- Deleting a data node should also not change the number of --- partitions with repartition=>false -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - --- reset to 3 partitions -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; --- Create the trigger function on the data nodes: -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; -$$); -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 1,2,3; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+----------------------+-------------- - 1 | 1 | db_dist_hypertable_1 | f - 1 | 1 | db_dist_hypertable_2 | f - 1 | 1 | db_dist_hypertable_3 | f - 2 | 2 | db_dist_hypertable_1 | f - 2 | 2 | db_dist_hypertable_2 | f - 2 | 2 | db_dist_hypertable_3 | f -(6 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - --- The constraints, indexes, and triggers on the hypertable -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------------------+------+---------------+----------------+--------------+------------+----------+----------- - disttable_device_check | c | {device} | - | (device > 0) | f | f | t - disttable_pkey | p | {time,device} | disttable_pkey | | f | f | t -(2 rows) - -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_idx | {time} | | f | f | f | -(3 rows) - -SELECT * FROM test.show_triggers('disttable'); - Trigger | Type | Function -------------------------+------+--------------------------------------- - _0_test_trigger_insert | 7 | test_trigger - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(2 rows) - --- Drop a column. This will make the attribute numbers of the --- hypertable's root relation differ from newly created chunks. It is --- a way to test that we properly handle attributed conversion between --- the root table and chunks -ALTER TABLE disttable DROP COLUMN color; --- EXPLAIN some inserts to see what plans and explain output for --- remote inserts look like -EXPLAIN (COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeCopy) - -> Custom Scan (ChunkDispatch) - -> Result -(6 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable - -> Custom Scan (DataNodeCopy) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - Remote SQL: COPY public.disttable ("time", device, temp) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - -> Result - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision -(11 rows) - --- Create some chunks through insertion -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 09:21', 3, 2.2), - ('2017-01-01 08:11', 3, 2.3), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2017-01-02 09:01', 2, 1.4), - ('2017-01-02 08:21', 2, 1.5), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-02 09:01', 87, 1.4), - ('2018-07-02 09:21', 87, 1.8), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 06:21', 13, 1.5), - ('2018-07-01 07:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5), - ('2018-07-01 09:21', 90, 2.8), - ('2018-07-01 08:21', 29, 1.2); --- EXPLAIN some updates/deletes to see what plans and explain output for --- remote operations look like -EXPLAIN (VERBOSE, COSTS FALSE) -UPDATE disttable SET temp = 3.7 WHERE device = 1; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------- - Update on public.disttable - Update on public.disttable - Foreign Update on _timescaledb_internal._dist_hyper_1_1_chunk disttable_1 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_1_chunk SET temp = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_1_4_chunk disttable_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_4_chunk SET temp = $2 WHERE ctid = $1 - -> Seq Scan on public.disttable - Output: disttable."time", disttable.device, NULL::integer, '3.7'::double precision, disttable.ctid - Filter: (disttable.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_1 - Output: disttable_1."time", disttable_1.device, '3.7'::double precision, disttable_1.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_2 - Output: disttable_2."time", disttable_2.device, '3.7'::double precision, disttable_2.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) FOR UPDATE -(17 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -DELETE FROM disttable WHERE device = 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------- - Delete on public.disttable - Delete on public.disttable - Foreign Delete on _timescaledb_internal._dist_hyper_1_1_chunk disttable_1 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ctid = $1 - Foreign Delete on _timescaledb_internal._dist_hyper_1_4_chunk disttable_2 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ctid = $1 - -> Seq Scan on public.disttable - Output: disttable.ctid - Filter: (disttable.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_1 - Output: disttable_1.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_2 - Output: disttable_2.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) FOR UPDATE -(17 rows) - --- Test distributed ANALYZE. --- --- First show no statistics --- reltuples is initially -1 before any VACUUM/ANALYZE has been run on PG14 -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 0 | 0 - _dist_hyper_1_2_chunk | f | 0 | 0 - _dist_hyper_1_3_chunk | f | 0 | 0 - _dist_hyper_1_4_chunk | f | 0 | 0 - _dist_hyper_1_5_chunk | f | 0 | 0 - _dist_hyper_1_6_chunk | f | 0 | 0 -(6 rows) - -ANALYZE disttable; --- Show updated statistics -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 2 | 1 - _dist_hyper_1_2_chunk | f | 3 | 1 - _dist_hyper_1_3_chunk | f | 3 | 1 - _dist_hyper_1_4_chunk | f | 3 | 1 - _dist_hyper_1_5_chunk | f | 3 | 1 - _dist_hyper_1_6_chunk | f | 4 | 1 -(6 rows) - --- Test distributed VACUUM. --- -VACUUM (FULL, ANALYZE) disttable; -VACUUM FULL disttable; -VACUUM disttable; -\set ON_ERROR_STOP 0 --- VACUUM VERBOSE is not supported at the moment -VACUUM VERBOSE disttable; -ERROR: operation not supported on distributed hypertable -\set ON_ERROR_STOP 1 --- Test prepared statement -PREPARE dist_insert (timestamptz, int, float) AS -INSERT INTO disttable VALUES ($1, $2, $3); -EXECUTE dist_insert ('2017-01-01 06:05', 1, 1.4); --- Show chunks created -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-----------------------+---------+--------------------------------------------------------------------------------------------- - 1 | 1 | _timescaledb_internal | _dist_hyper_1_1_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2 | 1 | _timescaledb_internal | _dist_hyper_1_2_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 3 | 1 | _timescaledb_internal | _dist_hyper_1_3_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 4 | 1 | _timescaledb_internal | _dist_hyper_1_4_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 5 | 1 | _timescaledb_internal | _dist_hyper_1_5_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 6 | 1 | _timescaledb_internal | _dist_hyper_1_6_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show that there are assigned node_chunk_id:s in chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show that chunks are created on data nodes and that each data node --- has their own unique slice in the space (device) dimension. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6 -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4 -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8 -(6 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3 -Mon Jan 02 09:01:00 2017 PST| 2| 1.4 -Mon Jan 02 08:21:00 2017 PST| 2| 1.5 -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4 -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5 -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4 -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1 -Sun Jan 01 09:21:00 2017 PST| 3| 2.2 -Sun Jan 01 08:11:00 2017 PST| 3| 2.3 -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7 -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5 -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8 -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2 -(7 rows) - - - remote_exec -------------- - -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+---------------------- - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_1 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_2 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_3 - 0 | 24576 | 0 | 24576 | -(4 rows) - --- Show what some queries would look like on the frontend -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT * FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: disttable."time", disttable.device, disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time", disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time", disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time", disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(18 rows) - -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -ORDER BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, avg(disttable.temp) - Group Key: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, disttable.temp - -> Merge Append - Sort Key: (time_bucket('@ 3 hours'::interval, disttable_1."time")), disttable_1.device - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: time_bucket('@ 3 hours'::interval, disttable_1."time"), disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: time_bucket('@ 3 hours'::interval, disttable_2."time"), disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: time_bucket('@ 3 hours'::interval, disttable_3."time"), disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - --- Execute some queries on the frontend and return the results -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -GROUP BY 1, 2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 1 | 1.2 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(8 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(7 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -WHERE temp > 2 -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 -(2 rows) - --- Test AsyncAppend when using min/max aggregates -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(24 rows) - -SELECT max(temp) -FROM disttable; - max ------ - 2.8 -(1 row) - --- Test turning off async append -SET timescaledb.enable_async_append = OFF; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable_1.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(22 rows) - -SET timescaledb.enable_async_append = ON; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT min(temp), max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: min(disttable.temp), max(disttable.temp) - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(20 rows) - -SELECT min(temp), max(temp) -FROM disttable; - min | max ------+----- - 1.1 | 2.8 -(1 row) - --- Test AsyncAppend when using window functions -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: disttable.device, disttable.temp, (avg(disttable.temp) OVER (?)) - Sort Key: disttable.device, disttable.temp - -> WindowAgg - Output: disttable.device, disttable.temp, avg(disttable.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: disttable.device, disttable.temp - -> Merge Append - Sort Key: disttable_1.device - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST -(24 rows) - -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - device | temp | avg ---------+------+------------------ - 1 | 1.1 | 1.23333333333333 - 1 | 1.2 | 1.23333333333333 - 1 | 1.4 | 1.23333333333333 - 2 | 1.3 | 1.4 - 2 | 1.4 | 1.4 - 2 | 1.5 | 1.4 - 3 | 2.1 | 2.2 - 3 | 2.2 | 2.2 - 3 | 2.3 | 2.2 - 13 | 1.4 | 1.43333333333333 - 13 | 1.4 | 1.43333333333333 - 13 | 1.5 | 1.43333333333333 - 29 | 1.2 | 1.35 - 29 | 1.5 | 1.35 - 87 | 1.4 | 1.6 - 87 | 1.6 | 1.6 - 87 | 1.8 | 1.6 - 90 | 2.7 | 2.75 - 90 | 2.8 | 2.75 -(19 rows) - --- Test remote explain --- Make sure that chunks_in function only expects one-dimensional integer arrays -\set ON_ERROR_STOP 0 -SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[[2], [1]]) -ORDER BY "time" DESC NULLS FIRST LIMIT 1; -ERROR: invalid number of array dimensions for chunks_in -\set ON_ERROR_STOP 1 -SET timescaledb.enable_remote_explain = ON; --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when using max(time). -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(time) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable."time" - -> Custom Scan (AsyncAppend) - Output: disttable."time" - -> Merge Append - Sort Key: disttable_1."time" DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time" - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_4_chunk, _dist_hyper_1_1_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_4_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk."time" - Index Cond: (_dist_hyper_1_4_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_1_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk."time" - Index Cond: (_dist_hyper_1_1_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time" - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_5_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk."time" - Index Cond: (_dist_hyper_1_5_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_3_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk."time" - Index Cond: (_dist_hyper_1_3_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time" - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_6_chunk, _dist_hyper_1_2_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_6_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk."time" - Index Cond: (_dist_hyper_1_6_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_2_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk."time" - Index Cond: (_dist_hyper_1_2_chunk."time" IS NOT NULL) - -(69 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_1_chunk.temp - -> Sort - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_3_chunk.temp - -> Sort - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_2_chunk.temp - -> Sort - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(66 rows) - --- Don't remote explain if there is no VERBOSE flag -EXPLAIN (COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------- - Result - InitPlan 1 (returns $0) - -> Limit - -> Custom Scan (AsyncAppend) - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on disttable disttable_1 - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 -(9 rows) - --- Test additional EXPLAIN flags -EXPLAIN (ANALYZE, VERBOSE, COSTS FALSE, BUFFERS OFF, TIMING OFF, SUMMARY OFF) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=1 loops=1) - Output: $0 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable.temp - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable.temp - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 (actual rows=1 loops=1) - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 (actual rows=1 loops=1) - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 (actual rows=1 loops=1) - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=7 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk (actual rows=4 loops=1) - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(72 rows) - --- The constraints, indexes, and triggers on foreign chunks. Only --- check constraints should recurse to foreign chunks (although they --- aren't enforced on a foreign table) -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) -(18 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that the chunks are assigned data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - --- Adding a new trigger should not recurse to foreign chunks -CREATE TRIGGER _1_test_trigger_insert - AFTER INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that we can create indexes on distributed hypertables and --- that they don't recurse to foreign chunks -CREATE INDEX ON disttable (time, device); -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_device_idx | {time,device} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - --- No index mappings should exist either -SELECT * FROM _timescaledb_catalog.chunk_index; - chunk_id | index_name | hypertable_id | hypertable_index_name -----------+------------+---------------+----------------------- -(0 rows) - --- Check that creating columns work -ALTER TABLE disttable ADD COLUMN "Color" int; -SELECT * FROM test.show_columns('disttable'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | t - temp | double precision | f - Color | integer | f -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_columns((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_columns ----------------------------------------------+------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_1_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_1_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_2_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_2_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_2_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_3_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_3_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_3_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_4_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_4_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_4_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_5_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_5_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_5_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_6_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_6_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_6_chunk | (Color,integer,f) -(24 rows) - --- Adding a new unique constraint should not recurse to foreign --- chunks, but a check constraint should -ALTER TABLE disttable ADD CONSTRAINT disttable_color_unique UNIQUE (time, device, "Color"); -ALTER TABLE disttable ADD CONSTRAINT disttable_temp_non_negative CHECK (temp > 0.0); -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) -(24 rows) - -SELECT cc.* -FROM (SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('disttable')) c, - _timescaledb_catalog.chunk_constraint cc -WHERE c.chunk_id = cc.chunk_id; - chunk_id | dimension_slice_id | constraint_name | hypertable_constraint_name -----------+--------------------+-----------------+---------------------------- - 1 | 2 | constraint_2 | - 1 | 1 | constraint_1 | - 2 | 3 | constraint_3 | - 2 | 1 | constraint_1 | - 3 | 4 | constraint_4 | - 3 | 1 | constraint_1 | - 4 | 2 | constraint_2 | - 4 | 5 | constraint_5 | - 5 | 4 | constraint_4 | - 5 | 5 | constraint_5 | - 6 | 3 | constraint_3 | - 6 | 5 | constraint_5 | -(12 rows) - --- Show contents after re-adding column -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | -(19 rows) - --- Test INSERTS with RETURNING. Since we previously dropped a column --- on the hypertable, this also tests that we handle conversion of the --- attribute numbers in the RETURNING clause, since they now differ --- between the hypertable root relation and the chunk currently --- RETURNING from. -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 4, 1, 9.8) -RETURNING time, "Color", temp; - time | Color | temp -------------------------------+-------+------ - Sat Sep 02 06:09:00 2017 PDT | 1 | 9.8 -(1 row) - -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-03 06:18', 9, 3, 8.7) -RETURNING 1; - ?column? ----------- - 1 -(1 row) - --- On conflict -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 6, 2, 10.5) -ON CONFLICT DO NOTHING; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 3| 1|_timescaledb_internal|_dist_hyper_1_9_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 3| 1|_timescaledb_internal|_dist_hyper_1_7_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [715827882, 1431655764]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} - 3| 1|_timescaledb_internal|_dist_hyper_1_8_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - - - remote_exec -------------- - -(1 row) - --- Show new row and that conflicting row is not inserted -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -(7 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -Sat Sep 02 06:09:00 2017 PDT| 4| 9.8| 1 -(7 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1| -Sun Jan 01 09:21:00 2017 PST| 3| 2.2| -Sun Jan 01 08:11:00 2017 PST| 3| 2.3| -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 3 -(8 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 --- ON CONFLICT DO NOTHING only works when index inference is omitted -\set VERBOSITY default -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device) DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_pkey" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device,"Color") DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT ON CONSTRAINT disttable_color_unique DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -\set VERBOSITY terse -SELECT * FROM disttable ORDER BY disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 3 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | -(22 rows) - --- ON CONFLICT only works with DO NOTHING for now -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-09 08:13', 7, 3, 27.5) -ON CONFLICT (time) DO UPDATE SET temp = 3.2; -ERROR: ON CONFLICT DO UPDATE not supported on distributed hypertables --- Test that an INSERT that would create a chunk does not work on a --- data node -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) - -ERROR: [db_dist_hypertable_1]: distributed hypertable member cannot create chunk on its own -\set ON_ERROR_STOP 1 --- However, INSERTs on a data node that does not create a chunk works. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE disttable SET "Color" = 4 WHERE "Color" = 3; -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 9 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(23 rows) - -WITH devices AS ( - SELECT DISTINCT device FROM disttable ORDER BY device -) -UPDATE disttable SET "Color" = 2 WHERE device = (SELECT device FROM devices LIMIT 1); -\set ON_ERROR_STOP 0 --- Updates referencing non-existing column -UPDATE disttable SET device = 4 WHERE no_such_column = 2; -ERROR: column "no_such_column" does not exist at character 39 -UPDATE disttable SET no_such_column = 4 WHERE device = 2; -ERROR: column "no_such_column" of relation "disttable" does not exist at character 22 --- Update to system column -UPDATE disttable SET tableoid = 4 WHERE device = 2; -ERROR: cannot assign to system column "tableoid" at character 22 -\set ON_ERROR_STOP 1 --- Test deletes (no rows deleted) -DELETE FROM disttable WHERE device = 3 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | -(3 rows) - -DELETE FROM disttable WHERE time IS NULL; --- Test deletes (rows deleted) -DELETE FROM disttable WHERE device = 4 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 -(1 row) - --- Query to show that rows are deleted -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | 2 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 2 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(19 rows) - --- Ensure rows are deleted on the data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| 2 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| 2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| 2 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -Sun Sep 03 06:09:00 2017 PDT| 1| 2| 2 -(8 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 4 -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Test TRUNCATE -TRUNCATE disttable; --- No data should remain -SELECT * FROM disttable; - time | device | temp | Color -------+--------+------+------- -(0 rows) - --- Metadata and tables cleaned up -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-------------+------------+---------------------+---------+--------+----------- -(0 rows) - -SELECT * FROM show_chunks('disttable'); - show_chunks -------------- -(0 rows) - --- Also cleaned up remotely -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM show_chunks('disttable'); -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- The hypertable view also shows no chunks and no data -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 0 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test underreplicated chunk warning -INSERT INTO underreplicated VALUES ('2017-01-01 06:01', 1, 1.1), - ('2017-01-02 07:01', 2, 3.5); -WARNING: insufficient number of data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+------------------------+---------+------------------------------------------------ - 10 | 2 | _timescaledb_internal | _dist_hyper_2_10_chunk | f | {"time": [1482969600000000, 1483574400000000]} -(1 row) - --- Show chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - --- Show that chunks are created on remote data nodes and that all --- data nodes/chunks have the same data due to replication -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE underreplicated SET temp = 2.0 WHERE device = 2 -RETURNING time, temp, device; - time | temp | device -------------------------------+------+-------- - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - -SELECT * FROM underreplicated; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(2 rows) - --- Show that all replica chunks are updated -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - - remote_exec -------------- - -(1 row) - -DELETE FROM underreplicated WHERE device = 2 -RETURNING *; - time | device | temp -------------------------------+--------+------ - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - --- Ensure deletes across all data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test hypertable creation fails on distributed error -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float); -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_3]: -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float) -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_hypertable('remotetable', 'time', replication_factor => 1); -ERROR: [db_dist_hypertable_3]: relation "remotetable" already exists --- Test distributed_hypertable creation fails with replication factor 0 -CREATE TABLE remotetable2(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_distributed_hypertable('remotetable2', 'time', replication_factor => 0); -WARNING: distributed hypertable is deprecated -ERROR: invalid replication factor -\set ON_ERROR_STOP 1 -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 1 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test distributed hypertable creation with many parameters -\c :TEST_DBNAME :ROLE_SUPERUSER ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE SCHEMA "T3sTSch"; -CREATE SCHEMA "Table\\Schema"; -CREATE SCHEMA "single'schema"; -GRANT ALL ON SCHEMA "T3sTSch" TO :ROLE_1; -GRANT ALL ON SCHEMA "Table\\Schema" TO :ROLE_1; -GRANT ALL ON SCHEMA "single'schema" TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE "Table\\Schema"."Param_Table"("time Col %#^#@$#" timestamptz, __region text, reading float); -SELECT * FROM create_distributed_hypertable('"Table\\Schema"."Param_Table"', 'time Col %#^#@$#', partitioning_column => '__region', -associated_schema_name => 'T3sTSch', associated_table_prefix => 'test*pre_', chunk_time_interval => interval '1 week', -create_default_indexes => FALSE, if_not_exists => TRUE, replication_factor => 2, -data_nodes => ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time Col %#^#@$#" - hypertable_id | schema_name | table_name | created ----------------+---------------+-------------+--------- - 4 | Table\\Schema | Param_Table | t -(1 row) - --- Test detach and attach data node -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, drop_remote_data => true); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 1 - detach_data_node ------------------- - 1 -(1 row) - --- Test attach_data_node. First show dimensions and currently attached --- servers. The number of slices in the space dimension should equal --- the number of servers since we didn't explicitly specify --- number_partitions -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 1 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_3 -(1 row) - -SELECT * FROM attach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" was increased to 2 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 3 | db_dist_hypertable_1 -(1 row) - --- Show updated metadata after attach -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_1 - Param_Table | db_dist_hypertable_3 -(2 rows) - --- Attach another data node but do not auto-repartition, i.e., --- increase the number of slices. -SELECT * FROM attach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', repartition => false); -WARNING: attaching data node is deprecated -WARNING: insufficient number of partitions for dimension "__region" - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 4 | db_dist_hypertable_2 -(1 row) - --- Number of slices should not be increased -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Manually increase the number of partitions -SELECT * FROM set_number_partitions('"Table\\Schema"."Param_Table"', 4); - set_number_partitions ------------------------ - -(1 row) - --- Verify hypertables on all data nodes -SELECT * FROM _timescaledb_catalog.hypertable; - id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compression_state | compressed_hypertable_id | replication_factor | status -----+---------------+-----------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+-------------------+--------------------------+--------------------+-------- - 1 | public | disttable | _timescaledb_internal | _dist_hyper_1 | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 1 | 0 - 2 | public | underreplicated | _timescaledb_internal | _dist_hyper_2 | 1 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 4 | 0 - 4 | Table\\Schema | Param_Table | T3sTSch | test*pre_ | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 2 | 0 -(3 rows) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+--------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 4 | _timescaledb_functions | get_partition_hash | | | | -(5 rows) - -SELECT * FROM test.show_triggers('"Table\\Schema"."Param_Table"'); - Trigger | Type | Function --------------------+------+--------------------------------------- - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.hypertable; -SELECT * FROM _timescaledb_catalog.dimension; -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_1]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_1]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_2]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 4|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_2]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_3]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_3]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - - remote_exec -------------- - -(1 row) - --- Verify that repartitioning works as expected on detach_data_node -SELECT * FROM detach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"', repartition => true); -WARNING: detaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 2 - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, repartition => false); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Test multi-dimensional hypertable. The add_dimension() command --- should be propagated to backends. -CREATE TABLE dimented_table (time timestamptz, column1 int, column2 timestamptz, column3 int); -SELECT * FROM create_distributed_hypertable('dimented_table', 'time', partitioning_column => 'column1', number_partitions => 4, replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1']); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 5 | public | dimented_table | t -(1 row) - --- Create one chunk to block add_dimension -INSERT INTO dimented_table VALUES('2017-01-01 06:01', 1, '2017-01-01 08:01', 1); -CREATE VIEW dimented_table_slices AS -SELECT c.id AS chunk_id, c.hypertable_id, ds.dimension_id, cc.dimension_slice_id, c.schema_name AS - chunk_schema, c.table_name AS chunk_table, ds.range_start, ds.range_end -FROM _timescaledb_catalog.chunk c -INNER JOIN _timescaledb_catalog.hypertable h ON (c.hypertable_id = h.id) -INNER JOIN _timescaledb_catalog.dimension td ON (h.id = td.hypertable_id) -INNER JOIN _timescaledb_catalog.dimension_slice ds ON (ds.dimension_id = td.id) -INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.dimension_slice_id = ds.id AND cc.chunk_id = c.id) -WHERE h.table_name = 'dimented_table' -ORDER BY c.id, ds.dimension_id; -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+------------------ - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 -(2 rows) - --- add_dimension() with existing data -SELECT * FROM add_dimension('dimented_table', 'column2', chunk_time_interval => interval '1 week'); -NOTICE: adding not-null constraint to column "column2" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 9 | public | dimented_table | column2 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(3 rows) - -SELECT * FROM add_dimension('dimented_table', 'column3', 4, partitioning_func => '_timescaledb_functions.get_partition_for_key'); - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 10 | public | dimented_table | column3 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 - 11 | 5 | 10 | 11 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(4 rows) - -SELECT * FROM dimented_table ORDER BY time; - time | column1 | column2 | column3 -------------------------------+---------+------------------------------+--------- - Sun Jan 01 06:01:00 2017 PST | 1 | Sun Jan 01 08:01:00 2017 PST | 1 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - -SELECT * FROM attach_data_node(:'DATA_NODE_2', 'dimented_table'); -WARNING: attaching data node is deprecated - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 5 | 5 | db_dist_hypertable_2 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - --- ensure data node has new dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.dimension; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time |timestamp with time zone|t | | | | 604800000000| | | - 7| 4|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 4|column2 |timestamp with time zone|t | | | | 604800000000| | | - 9| 4|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 5|time |timestamp with time zone|t | | | | 604800000000| | | - 9| 5|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | -10| 5|column2 |timestamp with time zone|t | | | | 604800000000| | | -11| 5|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - - remote_exec -------------- - -(1 row) - ---test per-data node queries --- Create some chunks through insertion -CREATE TABLE disttable_replicated(time timestamptz PRIMARY KEY, device int CHECK (device > 0), temp float, "Color" int); -SELECT * FROM create_hypertable('disttable_replicated', 'time', replication_factor => 2); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------------+--------- - 6 | public | disttable_replicated | t -(1 row) - -INSERT INTO disttable_replicated VALUES - ('2017-01-01 06:01', 1, 1.1, 1), - ('2017-01-01 08:01', 1, 1.2, 2), - ('2018-01-02 08:01', 2, 1.3, 3), - ('2019-01-01 09:11', 3, 2.1, 4), - ('2020-01-01 06:01', 5, 1.1, 10), - ('2020-01-01 08:01', 6, 1.2, 11), - ('2021-01-02 08:01', 7, 1.3, 12), - ('2022-01-01 09:11', 8, 2.1, 13); -SELECT * FROM disttable_replicated; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Wed Jan 01 06:01:00 2020 PST | 5 | 1.1 | 10 - Wed Jan 01 08:01:00 2020 PST | 6 | 1.2 | 11 - Tue Jan 02 08:01:00 2018 PST | 2 | 1.3 | 3 - Sat Jan 02 08:01:00 2021 PST | 7 | 1.3 | 12 - Tue Jan 01 09:11:00 2019 PST | 3 | 2.1 | 4 - Sat Jan 01 09:11:00 2022 PST | 8 | 2.1 | 13 -(8 rows) - -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---guc disables the optimization -SET timescaledb.enable_per_data_node_queries = FALSE; -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Append (actual rows=8 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_12_chunk."time", _dist_hyper_6_12_chunk.device, _dist_hyper_6_12_chunk.temp, _dist_hyper_6_12_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_12_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_13_chunk."time", _dist_hyper_6_13_chunk.device, _dist_hyper_6_13_chunk.temp, _dist_hyper_6_13_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_13_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_14_chunk."time", _dist_hyper_6_14_chunk.device, _dist_hyper_6_14_chunk.temp, _dist_hyper_6_14_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_14_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_15_chunk."time", _dist_hyper_6_15_chunk.device, _dist_hyper_6_15_chunk.temp, _dist_hyper_6_15_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_15_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_16_chunk."time", _dist_hyper_6_16_chunk.device, _dist_hyper_6_16_chunk.temp, _dist_hyper_6_16_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_16_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_17_chunk."time", _dist_hyper_6_17_chunk.device, _dist_hyper_6_17_chunk.temp, _dist_hyper_6_17_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_17_chunk -(31 rows) - -SET timescaledb.enable_per_data_node_queries = TRUE; ---test WHERE clause -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=0 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) -(21 rows) - ---test OR -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0 or "Color" = 11; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=3 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=3 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=1 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) -(21 rows) - ---test some chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2018-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=2 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) -(15 rows) - ---test all chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2002-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=0 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - One-Time Filter: false -(3 rows) - ---test cte -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH cte AS ( - SELECT * FROM disttable_replicated -) -SELECT * FROM cte; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---queries that involve updates/inserts are not optimized -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH devices AS ( - SELECT DISTINCT device FROM disttable_replicated ORDER BY device -) -UPDATE disttable_replicated SET device = 2 WHERE device = (SELECT device FROM devices LIMIT 1); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Update on public.disttable_replicated (actual rows=0 loops=1) - Update on public.disttable_replicated - Foreign Update on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_1 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_12_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_13_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_3 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_14_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_4 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_15_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_5 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_16_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_6 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_17_chunk SET device = $2 WHERE ctid = $1 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable_replicated_7.device - -> Unique (actual rows=1 loops=1) - Output: disttable_replicated_7.device - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable_replicated_7.device - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_replicated_8.device - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_8 (actual rows=1 loops=1) - Output: disttable_replicated_8.device - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_9 (actual rows=1 loops=1) - Output: disttable_replicated_9.device - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_10 (actual rows=1 loops=1) - Output: disttable_replicated_10.device - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Seq Scan on public.disttable_replicated (actual rows=0 loops=1) - Output: disttable_replicated."time", 2, disttable_replicated.temp, disttable_replicated."Color", disttable_replicated.ctid - Filter: (disttable_replicated.device = $0) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_1 (actual rows=2 loops=1) - Output: disttable_replicated_1."time", 2, disttable_replicated_1.temp, disttable_replicated_1."Color", disttable_replicated_1.ctid - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_12_chunk WHERE ((device = $1::integer)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", 2, disttable_replicated_2.temp, disttable_replicated_2."Color", disttable_replicated_2.ctid - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_13_chunk WHERE ((device = $1::integer)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_3 (actual rows=0 loops=1) - Output: disttable_replicated_3."time", 2, disttable_replicated_3.temp, disttable_replicated_3."Color", disttable_replicated_3.ctid - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_14_chunk WHERE ((device = $1::integer)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_4 (actual rows=0 loops=1) - Output: disttable_replicated_4."time", 2, disttable_replicated_4.temp, disttable_replicated_4."Color", disttable_replicated_4.ctid - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_15_chunk WHERE ((device = $1::integer)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_5 (actual rows=0 loops=1) - Output: disttable_replicated_5."time", 2, disttable_replicated_5.temp, disttable_replicated_5."Color", disttable_replicated_5.ctid - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_16_chunk WHERE ((device = $1::integer)) FOR UPDATE - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_6 (actual rows=0 loops=1) - Output: disttable_replicated_6."time", 2, disttable_replicated_6.temp, disttable_replicated_6."Color", disttable_replicated_6.ctid - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_17_chunk WHERE ((device = $1::integer)) FOR UPDATE -(74 rows) - --- Test inserts with smaller batch size and more tuples to reach full --- batch -SET timescaledb.max_insert_batch_size=4; -CREATE TABLE twodim (time timestamptz DEFAULT '2019-02-10 10:11', "Color" int DEFAULT 11 CHECK ("Color" > 0), temp float DEFAULT 22.1); --- Create a replicated table to ensure we handle that case correctly --- with batching -SELECT * FROM create_hypertable('twodim', 'time', 'Color', 3, replication_factor => 2, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2',:'DATA_NODE_3']); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 7 | public | twodim | t -(1 row) - -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------+-------+------ -(0 rows) - --- INSERT enough data to stretch across multiple batches per --- data node. Also return a system column. Although we write tuples to --- multiple data nodes, the returned tuple should only be the ones in the --- original insert statement (without the replica tuples). -WITH result AS ( - INSERT INTO twodim VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1) - RETURNING tableoid = 'twodim'::regclass AS is_tableoid, time, temp, "Color" -) SELECT * FROM result ORDER BY time; - is_tableoid | time | temp | Color --------------+------------------------------+------+------- - t | Wed Feb 01 06:01:00 2017 PST | 1.1 | 1 - t | Wed Feb 01 08:01:00 2017 PST | 1.2 | 1 - t | Fri Feb 02 08:01:00 2018 PST | 1.3 | 2 - t | Fri Feb 01 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 10:01:00 2019 PST | 1.2 | 5 - t | Sun Feb 03 11:11:00 2019 PST | 3.5 | 6 - t | Mon Feb 04 08:21:00 2019 PST | 6.6 | 4 - t | Mon Feb 04 10:11:00 2019 PST | 7.4 | 7 - t | Mon Feb 04 12:11:00 2019 PST | 2.1 | 8 - t | Tue Feb 05 13:31:00 2019 PST | 6.3 | 8 - t | Wed Feb 06 01:13:00 2019 PST | 7.9 | 7 - t | Wed Feb 06 02:11:00 2019 PST | 1.8 | 5 - t | Wed Feb 06 19:24:00 2019 PST | 5.9 | 9 - t | Thu Feb 07 09:33:00 2019 PST | 9.5 | 7 - t | Thu Feb 07 18:44:00 2019 PST | 9.7 | 5 - t | Thu Feb 07 20:24:00 2019 PST | | 6 - t | Fri Feb 08 08:54:00 2019 PST | 7.3 | 1 - t | Fri Feb 08 18:14:00 2019 PST | 8.2 | 4 - t | Sat Feb 09 19:23:00 2019 PST | 9.1 | 8 -(20 rows) - --- Test insert with default values and a batch size of 1. -SET timescaledb.max_insert_batch_size=1; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim DEFAULT VALUES; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - Batch size: 1 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - -> Result - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision -(12 rows) - -INSERT INTO twodim DEFAULT VALUES; --- Reset the batch size -SET timescaledb.max_insert_batch_size=4; --- Constraint violation error check --- --- Execute and filter mentioned data node name in the error message. -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ INSERT INTO twodim VALUES ('2019-02-10 17:54', 0, 10.2) $$, :'TEST_DBNAME'); -ERROR: [db_dist_hypertable_x]: new row for relation "_dist_hyper_7_23_chunk" violates check constraint "twodim_Color_check" -\set ON_ERROR_STOP 1 --- Disable batching, reverting to FDW tuple-by-tuple inserts. --- First EXPLAIN with batching turned on. -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - Batch size: 4 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3), ..., ($10, $11, $12) - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(12 rows) - -SET timescaledb.max_insert_batch_size=0; --- Compare without batching -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Insert on public.twodim - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(9 rows) - --- Insert without batching -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when multiple dimensions are involved. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT * FROM twodim -ORDER BY time; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: twodim."time", twodim."Color", twodim.temp - -> Merge Append - Sort Key: twodim_1."time" - -> Custom Scan (DataNodeScan) on public.twodim twodim_1 - Output: twodim_1."time", twodim_1."Color", twodim_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_7_18_chunk, _dist_hyper_7_22_chunk, _dist_hyper_7_25_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12, 14]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_18_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_18_chunk - Output: _dist_hyper_7_18_chunk."time", _dist_hyper_7_18_chunk."Color", _dist_hyper_7_18_chunk.temp - -> Index Scan Backward using _dist_hyper_7_22_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_22_chunk - Output: _dist_hyper_7_22_chunk."time", _dist_hyper_7_22_chunk."Color", _dist_hyper_7_22_chunk.temp - -> Index Scan Backward using _dist_hyper_7_25_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_25_chunk - Output: _dist_hyper_7_25_chunk."time", _dist_hyper_7_25_chunk."Color", _dist_hyper_7_25_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_2 - Output: twodim_2."time", twodim_2."Color", twodim_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_7_19_chunk, _dist_hyper_7_21_chunk, _dist_hyper_7_24_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 11, 13]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_19_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_19_chunk - Output: _dist_hyper_7_19_chunk."time", _dist_hyper_7_19_chunk."Color", _dist_hyper_7_19_chunk.temp - -> Index Scan Backward using _dist_hyper_7_21_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_21_chunk - Output: _dist_hyper_7_21_chunk."time", _dist_hyper_7_21_chunk."Color", _dist_hyper_7_21_chunk.temp - -> Index Scan Backward using _dist_hyper_7_24_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_24_chunk - Output: _dist_hyper_7_24_chunk."time", _dist_hyper_7_24_chunk."Color", _dist_hyper_7_24_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_3 - Output: twodim_3."time", twodim_3."Color", twodim_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_7_20_chunk, _dist_hyper_7_23_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_20_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_20_chunk - Output: _dist_hyper_7_20_chunk."time", _dist_hyper_7_20_chunk."Color", _dist_hyper_7_20_chunk.temp - -> Index Scan Backward using _dist_hyper_7_23_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_23_chunk - Output: _dist_hyper_7_23_chunk."time", _dist_hyper_7_23_chunk."Color", _dist_hyper_7_23_chunk.temp - -(56 rows) - -SET timescaledb.enable_remote_explain = OFF; --- Check results -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------------------------------+-------+------ - Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - Thu Feb 07 20:24:00 2019 PST | 6 | - Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 - Sun Feb 10 10:11:00 2019 PST | 11 | 22.1 - Sun Feb 10 16:23:00 2019 PST | 5 | 7.1 - Sun Feb 10 17:11:00 2019 PST | 7 | 3.2 -(23 rows) - -SELECT count(*) FROM twodim; - count -------- - 23 -(1 row) - --- Show distribution across data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM twodim -ORDER BY time; -SELECT count(*) FROM twodim; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_1]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -(12 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_1]: -count ------ - 12 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_2]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(19 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_2]: -count ------ - 19 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_3]: -time |Color|temp -----------------------------+-----+---- -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(15 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_3]: -count ------ - 15 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Distributed table with custom type that has no binary output -CREATE TABLE disttable_with_ct(time timestamptz, txn_id rxid, val float, info text); -SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 2); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------------+--------- - 8 | public | disttable_with_ct | t -(1 row) - --- Insert data with custom type -INSERT INTO disttable_with_ct VALUES - ('2019-01-01 01:01', 'ts-1-10-20-30', 1.1, 'a'), - ('2019-01-01 01:02', 'ts-1-11-20-30', 2.0, repeat('abc', 1000000)); -- TOAST --- Test queries on distributed table with custom type -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - -SET timescaledb.enable_connection_binary_data=false; -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - --- Test DELETE with replication -DELETE FROM disttable_with_ct WHERE info = 'a'; --- Check if row is gone -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(1 row) - --- Connect to data nodes to see if data is gone -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_1]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_2]: -time|txn_id|val|substring -----+------+---+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_3]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test single quote in names -SET SCHEMA 'single''schema'; -CREATE TABLE "disttable'quote"(time timestamptz, "device'quote" int, val float, info text); -SELECT public.create_distributed_hypertable( - 'disttable''quote', 'time', 'device''quote', data_nodes => ARRAY[:'DATA_NODE_1'] -); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------------- - (9,single'schema,disttable'quote,t) -(1 row) - -SET SCHEMA 'public'; -CREATE TABLE disttable_drop_chunks(time timestamptz, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable_drop_chunks', 'time', 'device', number_partitions => 3, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------------+--------- - 10 | public | disttable_drop_chunks | t -(1 row) - -INSERT INTO disttable_drop_chunks VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5); --- Show chunks on access node -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 27 | 10 | _timescaledb_internal | _dist_hyper_10_27_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 28 | 10 | _timescaledb_internal | _dist_hyper_10_28_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 29 | 10 | _timescaledb_internal | _dist_hyper_10_29_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show chunks on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 16| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 17| 9|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 16| 9|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 7|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 16| 7|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM drop_chunks('disttable_drop_chunks', older_than => '2018-01-01'::timestamptz); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_27_chunk - _timescaledb_internal._dist_hyper_10_28_chunk - _timescaledb_internal._dist_hyper_10_29_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------------------------------+--------+------- - Mon Jul 02 08:01:00 2018 PDT | 87 | 2 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1 - Sun Jul 01 09:11:00 2018 PDT | 90 | 3 - Sun Jul 01 08:01:00 2018 PDT | 29 | 2 -(4 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- test passing newer_than as interval -SELECT * FROM drop_chunks('disttable_drop_chunks', newer_than => interval '10 years'); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_30_chunk - _timescaledb_internal._dist_hyper_10_31_chunk - _timescaledb_internal._dist_hyper_10_32_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------+--------+------- -(0 rows) - -CREATE TABLE "weird nAme\\#^."(time bigint, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('"weird nAme\\#^."', 'time', 'device', 3, chunk_time_interval => 100, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 11 | public | weird nAme\\#^. | t -(1 row) - -INSERT INTO "weird nAme\\#^." VALUES - (300, 1, 1.1), - (400, 3, 2.1), - (350, 1, 1.2); -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- - 300 | 1 | 1 - 350 | 1 | 1 - 400 | 3 | 2 -(3 rows) - --- drop chunks using bigint as time -SELECT * FROM drop_chunks('"weird nAme\\#^."', older_than => 1000); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_33_chunk - _timescaledb_internal._dist_hyper_11_34_chunk -(2 rows) - -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- -(0 rows) - ------------------------------------------------------------------------------------------ --- Test that settings on hypertables are distributed to data nodes ------------------------------------------------------------------------------------------ -DROP TABLE disttable CASCADE; -CREATE TABLE disttable (time bigint, device int, temp float); -SELECT create_distributed_hypertable('disttable', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (12,public,disttable,t) -(1 row) - --- Show the dimension configuration on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -14| 9|time |bigint |t | | | | 1000000| | | -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test adding a space dimension. Should apply to data nodes as --- well. We're setting num_partitions lower than the number of servers --- and expect a warning. -SELECT * FROM add_dimension('disttable', 'device', 1, partitioning_func => '_timescaledb_functions.get_partition_hash'); -WARNING: insufficient number of partitions for dimension "device" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+------------+-------------+--------- - 22 | public | disttable | device | t -(1 row) - -CREATE INDEX disttable_device_time_idx ON disttable (device, time); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 1000000| | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Show that changing dimension settings apply to data nodes -SELECT * FROM set_chunk_time_interval('disttable', 2000000000::bigint); - set_chunk_time_interval -------------------------- - -(1 row) - -SELECT * FROM set_number_partitions('disttable', 3); - set_number_partitions ------------------------ - -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT' -$$); -SELECT * FROM set_integer_now_func('disttable', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - --- Show changes to dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Tests for using tablespaces with distributed hypertables -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE TABLESPACE :TABLESPACE_1 OWNER :ROLE_1 LOCATION :'spc1path'; -CREATE TABLESPACE :TABLESPACE_2 OWNER :ROLE_1 LOCATION :'spc2path'; -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: tablespace "db_dist_hypertable_1" is not attached to hypertable "disttable" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable'); - detach_tablespaces --------------------- - 0 -(1 row) - --- Continue to use previously attached tablespace, but block attach/detach -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_distributed_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (13,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_13_35_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable2'); - detach_tablespaces --------------------- - 0 -(1 row) - -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - --- Ensure tablespace API works for data nodes -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT detach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec($$ -SELECT detach_tablespaces('disttable2'); -$$); -DROP TABLE disttable2; -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint, replication_factor => 1); -NOTICE: adding not-null constraint to column "time" - create_hypertable --------------------------- - (14,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_14_36_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - -DROP TABLE disttable2; -DROP TABLESPACE :TABLESPACE_1; -DROP TABLESPACE :TABLESPACE_2; --- Make sure table qualified name is used in chunks_in function. Otherwise having a table name same as a column name might yield an error -CREATE TABLE dist_device(time timestamptz, dist_device int, temp float); -SELECT * FROM create_distributed_hypertable('dist_device', 'time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 15 | public | dist_device | t -(1 row) - -INSERT INTO dist_device VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2); -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM dist_device; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) -(5 rows) - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when only time partitioning is being used. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT "time", dist_device, temp FROM public.dist_device ORDER BY "time" ASC NULLS LAST; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Index Scan Backward using _dist_hyper_15_37_chunk_dist_device_time_idx on _timescaledb_internal._dist_hyper_15_37_chunk - Output: _dist_hyper_15_37_chunk."time", _dist_hyper_15_37_chunk.dist_device, _dist_hyper_15_37_chunk.temp - -(9 rows) - -SELECT * FROM dist_device; - time | dist_device | temp -------------------------------+-------------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 -(3 rows) - --- Test estimating relation size without stats -CREATE TABLE hyper_estimate(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('hyper_estimate', 'time', 'device', number_partitions => 3, replication_factor => 1, chunk_time_interval => INTERVAL '7 days'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 16 | public | hyper_estimate | t -(1 row) - --- This will enable us to more easily see estimates per chunk -SET timescaledb.enable_per_data_node_queries = false; --- Estimating chunk progress uses current timestamp so we override it for test purposes -SELECT test.tsl_override_current_timestamptz('2017-11-11 00:00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - --- Test estimates when backfilling. 3 chunks should be historical and 3 should be considered current when estimating. --- Note that estimate numbers are way off since we are using shared buffer size as starting point. This will not be --- an issue in 'production' like env since chunk size should be similar to shared buffer size. -INSERT INTO hyper_estimate VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); --- This will calculate the stats -ANALYZE hyper_estimate; -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..60021.38 rows=15 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) -(7 rows) - --- Let's insert data into a new chunk. This will result in chunk creation. -INSERT INTO hyper_estimate VALUES ('2019-11-11 06:01', 1, 1.1); --- We have stats for previous chunks so we can interpolate number of rows for the new chunk -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..70023.31 rows=17 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) - -> Foreign Scan on _dist_hyper_16_44_chunk (cost=10000.00..10001.93 rows=2 width=20) -(8 rows) - -CREATE TABLE devices ( - device_id INTEGER PRIMARY KEY, - device_name VARCHAR(10) -); -CALL distributed_exec($$ - CREATE TABLE devices(device_id INTEGER PRIMARY KEY, device_name VARCHAR(10)) -$$); -INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765'); -CALL distributed_exec($$ - INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765') -$$); -CREATE TABLE hyper ( - time TIMESTAMPTZ NOT NULL, - device INTEGER REFERENCES devices(device_id), - temp FLOAT -); -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours' -); -WARNING: distributed hypertable is deprecated -WARNING: distributed hypertable "hyper" has a foreign key to a non-distributed table - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 17 | public | hyper | t -(1 row) - --- Inserting some values should succeed. -INSERT INTO hyper VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM hyper -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 1 | 1.65 - Mon Jan 02 04:00:00 2017 PST | 2 | 1.4 - Mon Jan 02 07:00:00 2017 PST | 1 | 1.3 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.6 - Tue Jan 03 01:00:00 2017 PST | 3 | 3 - Sat Jan 13 01:00:00 2018 PST | 2 | 1.4 - Sat Jan 13 04:00:00 2018 PST | 2 | 3 - Sat Jan 13 16:00:00 2018 PST | 3 | 2 -(8 rows) - --- Add some devices on the access node only. Inserts should then fail. -INSERT INTO devices VALUES (6, 'E999'); -\set ON_ERROR_STOP 0 -INSERT INTO hyper VALUES ('2017-01-01 06:01', 6, 1.1); -ERROR: [db_dist_hypertable_1]: insert or update on table "_dist_hyper_17_45_chunk" violates foreign key constraint "26_17_hyper_device_fkey" -\set ON_ERROR_STOP 1 --- Test alter replication factor with data -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Dimension partitions should be updated to account for replication --- to additional data nodes -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1} - hyper | 29 | 715827882 | {db_dist_hypertable_2} - hyper | 29 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -SELECT * FROM set_replication_factor('hyper', 3); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------------------------------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3,db_dist_hypertable_1} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1,db_dist_hypertable_2} -(3 rows) - -INSERT INTO hyper VALUES ('2017-01-02 07:11', 1, 1.7); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-02-01 06:01', 1, 5.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------------------------------------- - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1} -(3 rows) - -INSERT INTO hyper VALUES ('2017-03-01 06:01', 1, 15.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', replication_factor => 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-04-01 06:01', 2, 45.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 14|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('hyper', replication_factor => 4); -ERROR: replication factor too large for hypertable "hyper" -\set ON_ERROR_STOP 1 -DROP TABLE hyper; -CALL distributed_exec($$ - DROP TABLE devices; -$$); -DROP TABLE devices; --- Test storage options are distributed to data nodes --- --- Make sure that options used during CREATE TABLE WITH and CREATE INDEX WITH --- are properly distributed. --- -CREATE TABLE disttable_with_relopts_1(time timestamptz NOT NULL, device int) WITH (fillfactor=10); -CREATE TABLE disttable_with_relopts_2(time timestamptz NOT NULL, device int) WITH (fillfactor=10, parallel_workers=1); -CREATE TABLE disttable_with_relopts_3(time timestamptz NOT NULL, device int); -CREATE INDEX disttable_with_relopts_3_idx ON disttable_with_relopts_3(device) WITH (fillfactor=20); -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_1', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 18 | public | disttable_with_relopts_1 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_2', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 19 | public | disttable_with_relopts_2 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_3', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 20 | public | disttable_with_relopts_3 | t -(1 row) - -INSERT INTO disttable_with_relopts_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -INSERT INTO disttable_with_relopts_2 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=10} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; - relname | reloptions ---------------------------+------------------------------------ - disttable_with_relopts_2 | {fillfactor=10,parallel_workers=1} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_3 | -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; - relname | reloptions -------------------------------+----------------- - disttable_with_relopts_3_idx | {fillfactor=20} -(1 row) - --- Ensure reloptions are not set for distributed hypertable chunks on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_19_57_chunk | - _dist_hyper_19_58_chunk | -(2 rows) - --- Ensure parent tables has proper storage options -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Ensure index has proper storage options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Make sure chunks derive parent reloptions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname|reloptions --------+---------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_57_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_58_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- ALTER TABLE SET/RESET support for distributed hypertable --- --- SET -ALTER TABLE disttable_with_relopts_1 SET (fillfactor=40); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=40} -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- RESET -ALTER TABLE disttable_with_relopts_1 RESET (fillfactor); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_1 | -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_55_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_56_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_with_relopts_1; -DROP TABLE disttable_with_relopts_2; -DROP TABLE disttable_with_relopts_3; --- Test SERIAL type column support for distributed hypertables --- -CREATE TABLE disttable_serial(time timestamptz NOT NULL, device int, id1 SERIAL, id2 SMALLSERIAL, id3 BIGSERIAL); -SELECT create_distributed_hypertable('disttable_serial', 'time', 'device'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (21,public,disttable_serial,t) -(1 row) - --- Show created columns (AN and DN tables must be exact) -SELECT * FROM test.show_columns('disttable_serial'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | f - id1 | integer | t - id2 | smallint | t - id3 | bigint | t -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * FROM test.show_columns('disttable_serial'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_1]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_2]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_3]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure DEFAULT expression is applied on the AN only -SELECT column_name, column_default -FROM information_schema.columns -WHERE table_name = 'disttable_serial'; - column_name | column_default --------------+----------------------------------------------- - time | - device | - id1 | nextval('disttable_serial_id1_seq'::regclass) - id2 | nextval('disttable_serial_id2_seq'::regclass) - id3 | nextval('disttable_serial_id3_seq'::regclass) -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_1]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_2]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_3]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure sequences were created on the AN only -INSERT INTO disttable_serial VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT currval('disttable_serial_id1_seq'::regclass), - currval('disttable_serial_id2_seq'::regclass), - currval('disttable_serial_id3_seq'::regclass); - currval | currval | currval ----------+---------+--------- - 5 | 5 | 5 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT currval('disttable_serial_id1_seq'::regclass); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT currval('disttable_serial_id1_seq'::regclass) -ERROR: [db_dist_hypertable_1]: relation "disttable_serial_id1_seq" does not exist -\set ON_ERROR_STOP 1 --- Verify that the data is getting spread over multiple data nodes with the --- serial values being set correctly -SELECT * from disttable_serial ORDER BY id1; - time | device | id1 | id2 | id3 -------------------------------+--------+-----+-----+----- - Sun Jan 01 06:01:00 2017 PST | 1 | 1 | 1 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2 | 2 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 3 | 3 | 3 - Mon Jan 02 08:01:00 2017 PST | 2 | 4 | 4 | 4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 5 | 5 | 5 -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * from disttable_serial ORDER BY id1; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_1]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 06:01:00 2017 PST| 1| 1| 1| 1 -Sun Jan 01 08:01:00 2017 PST| 1| 3| 3| 3 -Mon Jul 02 08:01:00 2018 PDT| 87| 5| 5| 5 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_2]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Mon Jan 02 08:01:00 2017 PST| 2| 4| 4| 4 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_3]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 09:11:00 2017 PST| 3| 2| 2| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_serial; --- Test insert batching case which will hit the limit of arguments for --- prepared statements (65k). --- --- Issue: #1702 --- distributed hypertable insert fails when # of columns are more than 65 --- --- Use default value -SET timescaledb.max_insert_batch_size TO 1000; -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int , - dummy6 int , - dummy7 int , - dummy8 int , - dummy9 int , - dummy10 int , - dummy11 int , - dummy12 int , - dummy13 int , - dummy14 int , - dummy15 int , - dummy16 int , - dummy17 int , - dummy18 int , - dummy19 int , - dummy20 int , - dummy21 int , - dummy22 int , - dummy23 int , - dummy24 int , - dummy25 int , - dummy26 int , - dummy27 int , - dummy28 int , - dummy29 int , - dummy30 int , - dummy31 int , - dummy32 int , - dummy33 int , - dummy34 int , - dummy35 int , - dummy36 int , - dummy37 int , - dummy38 int , - dummy39 int , - dummy40 int , - dummy41 int , - dummy42 int , - dummy43 int , - dummy44 int , - dummy45 int , - dummy46 int , - dummy47 int , - dummy48 int , - dummy49 int , - dummy50 int , - dummy51 int , - dummy52 int , - dummy53 int , - dummy54 int , - dummy55 int , - dummy56 int , - dummy57 int , - dummy58 int , - dummy59 int , - dummy60 int , - dummy61 int , - dummy62 int , - dummy63 int , - dummy64 int , - dummy65 int , - dummy66 int , - dummy67 int , - dummy68 int , - dummy69 int , - dummy70 int , - dummy71 int -); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (22,public,test_1702,t) -(1 row) - --- Original issue case --- --- Expect batch size to be lower than defined max_insert_batch_size --- -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; - QUERY PLAN ------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> ProjectSet - -> Result -(9 rows) - -INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; -SELECT count(*) from test_1702; - count -------- - 1500 -(1 row) - -DROP TABLE test_1702; --- --- Expect batch size to be similair to max_insert_batch_size --- -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int - ); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (23,public,test_1702,t) -(1 row) - -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -DROP TABLE test_1702; --- --- Test that creating a hypertable with a space dimension and --- if_not_exists works as expected, that is, the second call does not --- generate an error (and does not crash). --- -CREATE TABLE whatever ( - timestamp TIMESTAMPTZ NOT NULL, - user_id INT NOT NULL, - data JSONB -); -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | t -(1 row) - --- Check the hypertable sequence before and after call to ensure that --- the hypertable sequence was not increased with the second call. -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -NOTICE: table "whatever" is already a hypertable, skipping - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | f -(1 row) - -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - --- Test that creating a distributed hypertable from a table with data --- fails, and that migrate_data blocked. -CREATE TABLE dist_hypertable_1 ( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temp FLOAT -); -INSERT INTO dist_hypertable_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => FALSE); -WARNING: distributed hypertable is deprecated -ERROR: table "dist_hypertable_1" is not empty -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => TRUE); -WARNING: distributed hypertable is deprecated -ERROR: cannot migrate data for distributed hypertable -\set ON_ERROR_STOP 1 --- Test creating index with transaction per chunk on a distributed hypertable --- -DROP TABLE disttable; -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 25 | public | disttable | t -(1 row) - -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -\set ON_ERROR_STOP 0 -CREATE INDEX disttable_time_device_idx ON disttable (time, device) WITH (timescaledb.transaction_per_chunk); -ERROR: cannot use timescaledb.transaction_per_chunk with distributed hypertable -\set ON_ERROR_STOP 1 --- Test using system columns with distributed hypertable --- -CREATE TABLE dist_syscol(time timestamptz NOT NULL, color int, temp float); -SELECT * FROM create_distributed_hypertable('dist_syscol', 'time', 'color'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 26 | public | dist_syscol | t -(1 row) - -INSERT INTO dist_syscol VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1); --- Return chunk table as a source -SET timescaledb.enable_per_data_node_queries = false; -SELECT tableoid::regclass, * FROM dist_syscol; - tableoid | time | color | temp ------------------------------------------------+------------------------------+-------+------ - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - _timescaledb_internal._dist_hyper_26_73_chunk | Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - _timescaledb_internal._dist_hyper_26_74_chunk | Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_74_chunk | Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_75_chunk | Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - _timescaledb_internal._dist_hyper_26_76_chunk | Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - _timescaledb_internal._dist_hyper_26_76_chunk | Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - _timescaledb_internal._dist_hyper_26_76_chunk | Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - _timescaledb_internal._dist_hyper_26_77_chunk | Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - _timescaledb_internal._dist_hyper_26_78_chunk | Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - _timescaledb_internal._dist_hyper_26_79_chunk | Thu Feb 07 20:24:00 2019 PST | 6 | - _timescaledb_internal._dist_hyper_26_79_chunk | Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - _timescaledb_internal._dist_hyper_26_79_chunk | Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 -(20 rows) - --- Produce an error -SET timescaledb.enable_per_data_node_queries = true; -\set ON_ERROR_STOP 0 -SELECT tableoid::regclass, * FROM dist_syscol; -ERROR: system columns are not accessible on distributed hypertables with current settings -\set ON_ERROR_STOP 1 ------------------------ --- Test DataNodeCopy -- ------------------------ -SET timescaledb.enable_distributed_insert_with_copy=true; -DROP TABLE disttable; --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with DataNodeCopy -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 27 | public | disttable | t -(1 row) - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -CREATE TYPE highlow AS (high int, low int); -CALL distributed_exec($$ CREATE TYPE highlow AS (high int, low int) $$); -ALTER TABLE datatable ADD COLUMN minmaxes highlow[]; -INSERT INTO datatable (id, time, device, temp_c, minmaxes) VALUES - (1, '2017-01-01 06:01', 1, 1.2, ARRAY[(1,2)::highlow]), - (2, '2017-01-01 09:11', 3, 4.3, ARRAY[(2,3)::highlow]), - (3, '2017-01-01 08:01', 1, 7.3, ARRAY[(4,5)::highlow]), - (4, '2017-01-02 08:01', 2, 0.23, ARRAY[(6,7)::highlow]), - (5, '2018-07-02 08:01', 87, 0.0, ARRAY[(8,9)::highlow]), - (6, '2018-07-01 06:01', 13, 3.1, ARRAY[(10,11)::highlow]), - (7, '2018-07-01 09:11', 90, 10303.12, ARRAY[(12,13)::highlow]), - (8, '2018-07-01 08:01', 29, 64, ARRAY[(14,15)::highlow]); --- Show that DataNodeCopy is used instead of DataNodeDispatch. Should --- default to FORMAT binary in the remote SQL. Add RETURNING to show --- that it works. -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Remote SQL: COPY public.disttable (id, "time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(13 rows) - --- Perform the actual insert -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - --- Show that the data was added: -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - -SELECT count(*) FROM disttable; - count -------- - 8 -(1 row) - --- Add an array of a composite type to check that DataNodeCopy --- switches to text format if we use a table with an array of a custom --- type. There should be no "FORMAT binary" in the remote explain. -ALTER TABLE disttable ADD COLUMN minmaxes highlow[]; -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=56) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=56) - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - Remote SQL: COPY public.disttable (id, "time", device, temp_c, minmaxes) FROM STDIN - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=56) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes -(11 rows) - -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; --- Should have double amount of rows compared to before and half of --- them values in the new column. Note, must use TEXT format on the --- connection to make query work with custom type array. -SET timescaledb.enable_connection_binary_data=false; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -SELECT count(*) FROM disttable; - count -------- - 16 -(1 row) - --- Binary format should lead to data incompatibility in PG 13 and earlier, --- because the highlow data type has different oids on data and access nodes. --- Use this to test the deserialization error reporting. Newer PG version --- ignore this oid mismatch for non-builtin types. -SET timescaledb.enable_connection_binary_data=true; -\set ON_ERROR_STOP 0 -SET timescaledb.remote_data_fetcher = 'copy'; -SELECT * FROM disttable ORDER BY 1; -ERROR: wrong element type -SET timescaledb.remote_data_fetcher = 'cursor'; -SELECT * FROM disttable ORDER BY 1; -ERROR: wrong element type -\set ON_ERROR_STOP 1 -RESET timescaledb.remote_data_fetcher; --- Show that DataNodeCopy is NOT used when source hypertable and target hypertable --- of the SELECT are both distributed. Try subselects with LIMIT, RETURNING and --- different distributed hypertable as source -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(10 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable LIMIT 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> Limit - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(13 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(10 rows) - -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; -INSERT INTO disttable (time, device, temp_c) -SELECT * FROM hyper_estimate LIMIT 2; -SELECT count(*) FROM disttable; - count -------- - 34 -(1 row) - --- REMOVE a column on data nodes to check how errors are handled: -CALL distributed_exec($$ ALTER TABLE disttable DROP COLUMN minmaxes $$); -\set ON_ERROR_STOP 0 -INSERT INTO disttable SELECT * FROM datatable; -ERROR: [db_dist_hypertable_1]: column "minmaxes" of relation "disttable" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE disttable; --- Create a new table access method by reusing heap handler -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_2]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_3]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler - remote_exec -------------- - -(1 row) - --- Create distributed hypertable using non-default access method -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp_c float, temp_f float GENERATED ALWAYS AS (temp_c * 9 / 5 + 32) STORED) USING test_am; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 28 | public | disttable | t -(1 row) - --- Make sure that distributed hypertable created on data nodes is --- using the correct table access method -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_1]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_2]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_3]: -hypertable_amname ------------------ -test_am -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that basic operations are working as expected -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, -10.0), - ('2017-01-01 09:11', 3, -5.0), - ('2017-01-01 08:01', 1, 1.0), - ('2017-01-02 08:01', 2, 5.0), - ('2018-07-02 08:01', 87, 10.0), - ('2018-07-01 06:01', 13, 15.0), - ('2018-07-01 09:11', 90, 20.0), - ('2018-07-01 08:01', 29, 24.0); -SELECT * FROM disttable ORDER BY time; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Sun Jan 01 06:01:00 2017 PST | 1 | -10 | 14 - Sun Jan 01 08:01:00 2017 PST | 1 | 1 | 33.8 - Sun Jan 01 09:11:00 2017 PST | 3 | -5 | 23 - Mon Jan 02 08:01:00 2017 PST | 2 | 5 | 41 - Sun Jul 01 06:01:00 2018 PDT | 13 | 15 | 59 - Sun Jul 01 08:01:00 2018 PDT | 29 | 24 | 75.2 - Sun Jul 01 09:11:00 2018 PDT | 90 | 20 | 68 - Mon Jul 02 08:01:00 2018 PDT | 87 | 10 | 50 -(8 rows) - --- Show that GENERATED columns work for INSERT with RETURNING clause --- (should use DataNodeCopy) -TRUNCATE disttable; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeCopy) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - Remote SQL: COPY public.disttable ("time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision -(13 rows) - -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - --- Same values returned with SELECT: -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - -UPDATE disttable SET temp_c=40.0 WHERE device=1; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 -(1 row) - --- Insert another value -INSERT INTO disttable VALUES ('2017-09-01 06:01', 2, 30.0); -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(2 rows) - --- Delete a value based on the generated column -DELETE FROM disttable WHERE temp_f=104; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(1 row) - --- Test also with DataNodeDispatch -TRUNCATE disttable; -SET timescaledb.enable_distributed_insert_with_copy=false; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable("time", device, temp_c) VALUES ($1, $2, $3), ..., ($2998, $2999, $3000) RETURNING "time", device, temp_c, temp_f - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision -(14 rows) - -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Generated columns with SELECT -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Check distributed hypertable within procedure properly drops remote tables --- --- #3663 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (29,public,test,t) -(1 row) - -CREATE PROCEDURE test_drop() LANGUAGE PLPGSQL AS $$ -BEGIN - DROP TABLE test; -END -$$; -CALL test_drop(); -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (30,public,test,t) -(1 row) - -DROP TABLE test; --- Test that stable functions are calculated on the access node. --- --- As a stable function to test, use the timestamp -> timestamptz conversion --- that is stable because it uses the current timezone. --- We have to be careful about `timestamp < timestamptz` comparison. From postgres --- docs: --- When comparing a timestamp without time zone to a timestamp with time zone, --- the former value is assumed to be given in the time zone specified by the --- TimeZone configuration parameter, and is rotated to UTC for comparison to --- the latter value (which is already in UTC internally). --- We don't want this to happen on data node, so we cast the filter value to --- timestamp, and check that this cast happens on the access node and uses the --- current timezone. -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -CREATE TABLE test_tz (time timestamp, v int); -SELECT create_distributed_hypertable('test_tz','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (31,public,test_tz,t) -(1 row) - -INSERT INTO test_tz VALUES ('2018-01-02 12:00:00', 2), ('2018-01-02 11:00:00', 1), - ('2018-01-02 13:00:00', 3), ('2018-01-02 14:00:00', 4); -SET TIME ZONE 'Etc/GMT'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Normal WHERE clause on baserel -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 14:00:00 2018 | 4 -(2 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- Also test different code paths used with aggregation pushdown. -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 2 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- TODO: test HAVING here and in the later now() tests as well. --- Change the timezone and check that the conversion is applied correctly. -SET TIME ZONE 'Etc/GMT+1'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 11:00:00 2018 -(1 row) - -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 12:00:00 2018 | 2 - Tue Jan 02 14:00:00 2018 | 4 -(3 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(30 rows) - -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 3 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(29 rows) - --- Conversion to timestamptz cannot be evaluated at the access node, because the --- argument is a column reference. -SELECT count(*) FROM test_tz WHERE time::timestamptz > now(); - count -------- - 0 -(1 row) - --- According to our docs, JIT is not recommended for use on access node in --- multi-node environment. Turn it off so that it doesn't ruin EXPLAIN for the --- next query. -SET jit = 0; --- Test that operators are evaluated as well. Comparison of timestamp with --- timestamptz is a stable operator, and comparison of two timestamps is an --- immutable operator. This also test that immutable functions using these --- operators as arguments are evaluated. -EXPLAIN (verbose, costs off) -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT * FROM test_tz, dummy -WHERE time > x - + (x = x)::int -- stable - * (x = '2018-01-02 11:00:00'::timestamp)::int -- immutable - * INTERVAL '1 hour'; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v, (('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- Reference value for the above test. -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT x + (x = x)::int * (x = '2018-01-02 11:00:00'::timestamp)::int * INTERVAL '1 hour' -FROM dummy; - ?column? --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Exercise some more stable timestamp-related functions. -EXPLAIN (COSTS OFF, VERBOSE) -SELECT * FROM test_tz WHERE date_trunc('month', time) > date_in('2021-01-01') - AND time::time > '00:00:00'::time - + (INTERVAL '1 hour') * date_part('hour', INTERVAL '1 hour'); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Filter: (((_dist_hyper_31_97_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_97_chunk."time") > '2021-01-01'::date)) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Filter: (((_dist_hyper_31_95_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_95_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Filter: (((_dist_hyper_31_96_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_96_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Filter: (((_dist_hyper_31_98_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_98_chunk."time") > '2021-01-01'::date)) - -(30 rows) - --- Check that the test function for partly overriding now() works. It's very --- hacky and only has effect when we estimate some costs or evaluate sTABLE --- functions in quals on access node, and has no effect in other cases. --- Consider deleting it altogether. -SELECT test.tsl_override_current_timestamptz('2018-01-02 12:00:00 +00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -SELECT count(*) FROM test_tz WHERE time > now(); - count -------- - 3 -(1 row) - -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -RESET TIME ZONE; -DROP TABLE test_tz; --- Check that now() is evaluated on the access node. Also check that it is evaluated --- anew on every execution of a prepared statement. -CREATE TABLE test_now (time timestamp, v int); -SELECT create_distributed_hypertable('test_now','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (32,public,test_now,t) -(1 row) - -PREPARE test_query as -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; -; -BEGIN; -- to fix the value of now(); -INSERT INTO test_now VALUES - (now(), 1), (now() + INTERVAL '1 hour', 1), - (now() + INTERVAL '2 hour', 2 ), (now() + INTERVAL '3 hour', 3); -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - --- Also test different code paths used with aggregation pushdown. --- We can't run EXPLAIN here, because now() is different every time. But the --- strict equality should be enough to detect if now() is being erroneously --- evaluated on data node, where it will differ from time to time. -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 1 -(1 row) - -COMMIT; --- now() will be different in a new transaction. -BEGIN; -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 0 -(1 row) - -COMMIT; -DROP TABLE test_now; -DEALLOCATE test_query; --- Check enabling distributed compression within a --- procedure/function works --- --- #3705 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (33,public,test,t) -(1 row) - -CREATE PROCEDURE test_set_compression() LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); -END -$$; -CALL test_set_compression(); -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_33_103_chunk -(1 row) - -DROP TABLE test; -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (34,public,test,t) -(1 row) - -CREATE FUNCTION test_set_compression_func() RETURNS BOOL LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); - RETURN TRUE; -END -$$; -SELECT test_set_compression_func(); - test_set_compression_func ---------------------------- - t -(1 row) - -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_34_104_chunk -(1 row) - -DROP TABLE test; --- Fix ALTER SET/DROP NULL constraint on distributed hypertable --- --- #3860 --- -CREATE TABLE test (time timestamp NOT NULL, my_column int NOT NULL); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (35,public,test,t) -(1 row) - -\set ON_ERROR_STOP 0 -INSERT INTO test VALUES (now(), NULL); -ERROR: [db_dist_hypertable_3]: null value in column "my_column" of relation "_dist_hyper_35_105_chunk" violates not-null constraint -\set ON_ERROR_STOP 1 -ALTER TABLE test ALTER COLUMN my_column DROP NOT NULL; -INSERT INTO test VALUES (now(), NULL); -\set ON_ERROR_STOP 0 -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -ERROR: [db_dist_hypertable_3]: column "my_column" of relation "_dist_hyper_35_106_chunk" contains null values -\set ON_ERROR_STOP 1 -DELETE FROM test; -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -DROP TABLE test; --- Test insert into distributed hypertable with pruned chunks -CREATE TABLE pruned_chunks_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_1', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_1 -(1 row) - -INSERT INTO pruned_chunks_1 VALUES ('2020-12-09',1,32.2); -CREATE TABLE pruned_chunks_2(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); --- Convert the table to a distributed hypertable -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_2', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_2 -(1 row) - -insert into pruned_chunks_2 select * from pruned_chunks_1; -insert into pruned_chunks_2 select * from pruned_chunks_1 WHERE time > '2022-01-01'; --- TEST freeze_chunk api. does not work for distributed chunks -SELECT chunk_schema || '.' || chunk_name as "CHNAME" -FROM timescaledb_information.chunks -WHERE hypertable_name = 'pruned_chunks_1' -ORDER BY chunk_name LIMIT 1 -\gset -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( :'CHNAME'); -ERROR: operation not supported on distributed chunk or foreign table "_dist_hyper_36_107_chunk" -\set ON_ERROR_STOP 1 ---TEST freeze_chunk api for regular hypertables. Works only for >= PG14 -CREATE TABLE freeze_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_hypertable('freeze_1', 'time'); - table_name ------------- - freeze_1 -(1 row) - -INSERT INTO freeze_1 VALUES ('2020-12-09',1,32.2); -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( ch) FROM ( select show_chunks('freeze_1') ch ) q; -ERROR: freeze chunk supported only for PG14 or greater -\set ON_ERROR_STOP 1 -DROP TABLE pruned_chunks_1; -DROP TABLE pruned_chunks_2; --- Cleanup -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_hypertable-14.out b/tsl/test/expected/dist_hypertable-14.out deleted file mode 100644 index a10d414f52b..00000000000 --- a/tsl/test/expected/dist_hypertable-14.out +++ /dev/null @@ -1,6299 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_1 | db_dist_hypertable_1 | t | t | t - db_dist_hypertable_2 | db_dist_hypertable_2 | t | t | t - db_dist_hypertable_3 | db_dist_hypertable_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; --- Import testsupport.sql file to data nodes -\unset ECHO -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; ---Ensure INSERTs use DataNodeDispatch. DataNodeCopy is tested later -SET timescaledb.enable_distributed_insert_with_copy=false; --- Verify lack of tables -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -\set ON_ERROR_STOP 0 --- Test that one cannot directly create TimescaleDB foreign tables -CREATE FOREIGN TABLE foreign_table (time timestamptz, device int, temp float) SERVER :DATA_NODE_1; -ERROR: operation not supported -\set ON_ERROR_STOP 1 --- Create distributed hypertables. Add a trigger and primary key --- constraint to test how those work -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), color int, temp float, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 1); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - --- Increase the number of partitions. Expect warning since still too --- low. Dimension partitions should be updated to reflect new --- partitioning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} -(1 row) - -SELECT * FROM set_number_partitions('disttable', 2); -WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - --- Set number of partitions equal to the number of servers should not --- raise a warning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show the number of slices -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'disttable'; - table_name | column_name | num_slices -------------+-------------+------------ - disttable | device | 3 - disttable | time | -(2 rows) - --- This table tests both 1-dimensional tables and under-replication --- (replication_factor > num_data_nodes). -CREATE TABLE underreplicated(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- can't create an under-replicated hypertable -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -ERROR: replication factor too large for hypertable "underreplicated" -\set ON_ERROR_STOP 1 -RESET ROLE; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node(:'DATA_NODE_4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_4 | db_dist_hypertable_4 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_4 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 2 | public | underreplicated | t -(1 row) - --- test that attaching a data node to an existing hypertable with --- repartition=>false does not change the number of partitions when --- number of partitions is greater than number of data nodes. -SELECT * FROM set_number_partitions('disttable', 8, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - -SELECT attach_data_node(:'DATA_NODE_4', 'disttable', repartition => false); -WARNING: attaching data node is deprecated - attach_data_node ----------------------------- - (1,2,db_dist_hypertable_4) -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_4} - disttable | 2 | 1073741820 | {db_dist_hypertable_1} - disttable | 2 | 1342177275 | {db_dist_hypertable_2} - disttable | 2 | 1610612730 | {db_dist_hypertable_3} - disttable | 2 | 1879048185 | {db_dist_hypertable_4} -(8 rows) - ---create new session to clear out connections -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_4', force => true, drop_database => true, repartition => false); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "underreplicated" - delete_data_node ------------------- - t -(1 row) - -SET ROLE :ROLE_1; --- Deleting a data node should also not change the number of --- partitions with repartition=>false -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - --- reset to 3 partitions -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; --- Create the trigger function on the data nodes: -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; -$$); -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 1,2,3; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+----------------------+-------------- - 1 | 1 | db_dist_hypertable_1 | f - 1 | 1 | db_dist_hypertable_2 | f - 1 | 1 | db_dist_hypertable_3 | f - 2 | 2 | db_dist_hypertable_1 | f - 2 | 2 | db_dist_hypertable_2 | f - 2 | 2 | db_dist_hypertable_3 | f -(6 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - --- The constraints, indexes, and triggers on the hypertable -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------------------+------+---------------+----------------+--------------+------------+----------+----------- - disttable_device_check | c | {device} | - | (device > 0) | f | f | t - disttable_pkey | p | {time,device} | disttable_pkey | | f | f | t -(2 rows) - -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_idx | {time} | | f | f | f | -(3 rows) - -SELECT * FROM test.show_triggers('disttable'); - Trigger | Type | Function -------------------------+------+--------------------------------------- - _0_test_trigger_insert | 7 | test_trigger - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(2 rows) - --- Drop a column. This will make the attribute numbers of the --- hypertable's root relation differ from newly created chunks. It is --- a way to test that we properly handle attributed conversion between --- the root table and chunks -ALTER TABLE disttable DROP COLUMN color; --- EXPLAIN some inserts to see what plans and explain output for --- remote inserts look like -EXPLAIN (COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeCopy) - -> Custom Scan (ChunkDispatch) - -> Result -(6 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable - -> Custom Scan (DataNodeCopy) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - Remote SQL: COPY public.disttable ("time", device, temp) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - -> Result - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision -(11 rows) - --- Create some chunks through insertion -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 09:21', 3, 2.2), - ('2017-01-01 08:11', 3, 2.3), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2017-01-02 09:01', 2, 1.4), - ('2017-01-02 08:21', 2, 1.5), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-02 09:01', 87, 1.4), - ('2018-07-02 09:21', 87, 1.8), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 06:21', 13, 1.5), - ('2018-07-01 07:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5), - ('2018-07-01 09:21', 90, 2.8), - ('2018-07-01 08:21', 29, 1.2); --- EXPLAIN some updates/deletes to see what plans and explain output for --- remote operations look like -EXPLAIN (VERBOSE, COSTS FALSE) -UPDATE disttable SET temp = 3.7 WHERE device = 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ - Update on public.disttable - Update on public.disttable disttable_1 - Foreign Update on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_1_chunk SET temp = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_4_chunk SET temp = $2 WHERE ctid = $1 - -> Result - Output: '3.7'::double precision, disttable.tableoid, disttable.ctid, (NULL::record) - -> Append - -> Seq Scan on public.disttable disttable_1 - Output: disttable_1.tableoid, disttable_1.ctid, NULL::record - Filter: (disttable_1.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Output: disttable_2.tableoid, disttable_2.ctid, disttable_2.* - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, temp, ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Output: disttable_3.tableoid, disttable_3.ctid, disttable_3.* - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, temp, ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) -(20 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -DELETE FROM disttable WHERE device = 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Delete on public.disttable - Delete on public.disttable disttable_1 - Foreign Delete on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ctid = $1 - Foreign Delete on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ctid = $1 - -> Append - -> Seq Scan on public.disttable disttable_1 - Output: disttable_1.tableoid, disttable_1.ctid - Filter: (disttable_1.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Output: disttable_2.tableoid, disttable_2.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Output: disttable_3.tableoid, disttable_3.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) -(18 rows) - --- Test distributed ANALYZE. --- --- First show no statistics --- reltuples is initially -1 before any VACUUM/ANALYZE has been run on PG14 -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 0 | 0 - _dist_hyper_1_2_chunk | f | 0 | 0 - _dist_hyper_1_3_chunk | f | 0 | 0 - _dist_hyper_1_4_chunk | f | 0 | 0 - _dist_hyper_1_5_chunk | f | 0 | 0 - _dist_hyper_1_6_chunk | f | 0 | 0 -(6 rows) - -ANALYZE disttable; --- Show updated statistics -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 2 | 1 - _dist_hyper_1_2_chunk | f | 3 | 1 - _dist_hyper_1_3_chunk | f | 3 | 1 - _dist_hyper_1_4_chunk | f | 3 | 1 - _dist_hyper_1_5_chunk | f | 3 | 1 - _dist_hyper_1_6_chunk | f | 4 | 1 -(6 rows) - --- Test distributed VACUUM. --- -VACUUM (FULL, ANALYZE) disttable; -VACUUM FULL disttable; -VACUUM disttable; -\set ON_ERROR_STOP 0 --- VACUUM VERBOSE is not supported at the moment -VACUUM VERBOSE disttable; -ERROR: operation not supported on distributed hypertable -\set ON_ERROR_STOP 1 --- Test prepared statement -PREPARE dist_insert (timestamptz, int, float) AS -INSERT INTO disttable VALUES ($1, $2, $3); -EXECUTE dist_insert ('2017-01-01 06:05', 1, 1.4); --- Show chunks created -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-----------------------+---------+--------------------------------------------------------------------------------------------- - 1 | 1 | _timescaledb_internal | _dist_hyper_1_1_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2 | 1 | _timescaledb_internal | _dist_hyper_1_2_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 3 | 1 | _timescaledb_internal | _dist_hyper_1_3_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 4 | 1 | _timescaledb_internal | _dist_hyper_1_4_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 5 | 1 | _timescaledb_internal | _dist_hyper_1_5_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 6 | 1 | _timescaledb_internal | _dist_hyper_1_6_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show that there are assigned node_chunk_id:s in chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show that chunks are created on data nodes and that each data node --- has their own unique slice in the space (device) dimension. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6 -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4 -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8 -(6 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3 -Mon Jan 02 09:01:00 2017 PST| 2| 1.4 -Mon Jan 02 08:21:00 2017 PST| 2| 1.5 -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4 -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5 -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4 -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1 -Sun Jan 01 09:21:00 2017 PST| 3| 2.2 -Sun Jan 01 08:11:00 2017 PST| 3| 2.3 -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7 -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5 -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8 -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2 -(7 rows) - - - remote_exec -------------- - -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+---------------------- - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_1 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_2 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_3 - 0 | 24576 | 0 | 24576 | -(4 rows) - --- Show what some queries would look like on the frontend -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT * FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: disttable."time", disttable.device, disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time", disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time", disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time", disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(18 rows) - -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -ORDER BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, avg(disttable.temp) - Group Key: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, disttable.temp - -> Merge Append - Sort Key: (time_bucket('@ 3 hours'::interval, disttable_1."time")), disttable_1.device - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: time_bucket('@ 3 hours'::interval, disttable_1."time"), disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: time_bucket('@ 3 hours'::interval, disttable_2."time"), disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: time_bucket('@ 3 hours'::interval, disttable_3."time"), disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - --- Execute some queries on the frontend and return the results -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -GROUP BY 1, 2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 1 | 1.2 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(8 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(7 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -WHERE temp > 2 -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 -(2 rows) - --- Test AsyncAppend when using min/max aggregates -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(24 rows) - -SELECT max(temp) -FROM disttable; - max ------ - 2.8 -(1 row) - --- Test turning off async append -SET timescaledb.enable_async_append = OFF; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable_1.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(22 rows) - -SET timescaledb.enable_async_append = ON; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT min(temp), max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: min(disttable.temp), max(disttable.temp) - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(20 rows) - -SELECT min(temp), max(temp) -FROM disttable; - min | max ------+----- - 1.1 | 2.8 -(1 row) - --- Test AsyncAppend when using window functions -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: disttable.device, disttable.temp, (avg(disttable.temp) OVER (?)) - Sort Key: disttable.device, disttable.temp - -> WindowAgg - Output: disttable.device, disttable.temp, avg(disttable.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: disttable.device, disttable.temp - -> Merge Append - Sort Key: disttable_1.device - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST -(24 rows) - -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - device | temp | avg ---------+------+------------------ - 1 | 1.1 | 1.23333333333333 - 1 | 1.2 | 1.23333333333333 - 1 | 1.4 | 1.23333333333333 - 2 | 1.3 | 1.4 - 2 | 1.4 | 1.4 - 2 | 1.5 | 1.4 - 3 | 2.1 | 2.2 - 3 | 2.2 | 2.2 - 3 | 2.3 | 2.2 - 13 | 1.4 | 1.43333333333333 - 13 | 1.4 | 1.43333333333333 - 13 | 1.5 | 1.43333333333333 - 29 | 1.2 | 1.35 - 29 | 1.5 | 1.35 - 87 | 1.4 | 1.6 - 87 | 1.6 | 1.6 - 87 | 1.8 | 1.6 - 90 | 2.7 | 2.75 - 90 | 2.8 | 2.75 -(19 rows) - --- Test remote explain --- Make sure that chunks_in function only expects one-dimensional integer arrays -\set ON_ERROR_STOP 0 -SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[[2], [1]]) -ORDER BY "time" DESC NULLS FIRST LIMIT 1; -ERROR: invalid number of array dimensions for chunks_in -\set ON_ERROR_STOP 1 -SET timescaledb.enable_remote_explain = ON; --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when using max(time). -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(time) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable."time" - -> Custom Scan (AsyncAppend) - Output: disttable."time" - -> Merge Append - Sort Key: disttable_1."time" DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time" - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_4_chunk, _dist_hyper_1_1_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_4_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk."time" - Index Cond: (_dist_hyper_1_4_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_1_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk."time" - Index Cond: (_dist_hyper_1_1_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time" - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_5_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk."time" - Index Cond: (_dist_hyper_1_5_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_3_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk."time" - Index Cond: (_dist_hyper_1_3_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time" - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_6_chunk, _dist_hyper_1_2_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_6_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk."time" - Index Cond: (_dist_hyper_1_6_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_2_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk."time" - Index Cond: (_dist_hyper_1_2_chunk."time" IS NOT NULL) - -(69 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_1_chunk.temp - -> Sort - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_3_chunk.temp - -> Sort - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_2_chunk.temp - -> Sort - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(66 rows) - --- Don't remote explain if there is no VERBOSE flag -EXPLAIN (COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------- - Result - InitPlan 1 (returns $0) - -> Limit - -> Custom Scan (AsyncAppend) - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on disttable disttable_1 - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 -(9 rows) - --- Test additional EXPLAIN flags -EXPLAIN (ANALYZE, VERBOSE, COSTS FALSE, BUFFERS OFF, TIMING OFF, SUMMARY OFF) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=1 loops=1) - Output: $0 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable.temp - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable.temp - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 (actual rows=1 loops=1) - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 (actual rows=1 loops=1) - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 (actual rows=1 loops=1) - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=7 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk (actual rows=4 loops=1) - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(72 rows) - --- The constraints, indexes, and triggers on foreign chunks. Only --- check constraints should recurse to foreign chunks (although they --- aren't enforced on a foreign table) -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) -(18 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that the chunks are assigned data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - --- Adding a new trigger should not recurse to foreign chunks -CREATE TRIGGER _1_test_trigger_insert - AFTER INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that we can create indexes on distributed hypertables and --- that they don't recurse to foreign chunks -CREATE INDEX ON disttable (time, device); -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_device_idx | {time,device} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - --- No index mappings should exist either -SELECT * FROM _timescaledb_catalog.chunk_index; - chunk_id | index_name | hypertable_id | hypertable_index_name -----------+------------+---------------+----------------------- -(0 rows) - --- Check that creating columns work -ALTER TABLE disttable ADD COLUMN "Color" int; -SELECT * FROM test.show_columns('disttable'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | t - temp | double precision | f - Color | integer | f -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_columns((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_columns ----------------------------------------------+------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_1_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_1_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_2_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_2_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_2_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_3_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_3_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_3_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_4_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_4_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_4_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_5_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_5_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_5_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_6_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_6_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_6_chunk | (Color,integer,f) -(24 rows) - --- Adding a new unique constraint should not recurse to foreign --- chunks, but a check constraint should -ALTER TABLE disttable ADD CONSTRAINT disttable_color_unique UNIQUE (time, device, "Color"); -ALTER TABLE disttable ADD CONSTRAINT disttable_temp_non_negative CHECK (temp > 0.0); -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) -(24 rows) - -SELECT cc.* -FROM (SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('disttable')) c, - _timescaledb_catalog.chunk_constraint cc -WHERE c.chunk_id = cc.chunk_id; - chunk_id | dimension_slice_id | constraint_name | hypertable_constraint_name -----------+--------------------+-----------------+---------------------------- - 1 | 2 | constraint_2 | - 1 | 1 | constraint_1 | - 2 | 3 | constraint_3 | - 2 | 1 | constraint_1 | - 3 | 4 | constraint_4 | - 3 | 1 | constraint_1 | - 4 | 2 | constraint_2 | - 4 | 5 | constraint_5 | - 5 | 4 | constraint_4 | - 5 | 5 | constraint_5 | - 6 | 3 | constraint_3 | - 6 | 5 | constraint_5 | -(12 rows) - --- Show contents after re-adding column -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | -(19 rows) - --- Test INSERTS with RETURNING. Since we previously dropped a column --- on the hypertable, this also tests that we handle conversion of the --- attribute numbers in the RETURNING clause, since they now differ --- between the hypertable root relation and the chunk currently --- RETURNING from. -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 4, 1, 9.8) -RETURNING time, "Color", temp; - time | Color | temp -------------------------------+-------+------ - Sat Sep 02 06:09:00 2017 PDT | 1 | 9.8 -(1 row) - -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-03 06:18', 9, 3, 8.7) -RETURNING 1; - ?column? ----------- - 1 -(1 row) - --- On conflict -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 6, 2, 10.5) -ON CONFLICT DO NOTHING; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 3| 1|_timescaledb_internal|_dist_hyper_1_9_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 3| 1|_timescaledb_internal|_dist_hyper_1_7_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [715827882, 1431655764]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} - 3| 1|_timescaledb_internal|_dist_hyper_1_8_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - - - remote_exec -------------- - -(1 row) - --- Show new row and that conflicting row is not inserted -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -(7 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -Sat Sep 02 06:09:00 2017 PDT| 4| 9.8| 1 -(7 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1| -Sun Jan 01 09:21:00 2017 PST| 3| 2.2| -Sun Jan 01 08:11:00 2017 PST| 3| 2.3| -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 3 -(8 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 --- ON CONFLICT DO NOTHING only works when index inference is omitted -\set VERBOSITY default -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device) DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_pkey" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device,"Color") DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT ON CONSTRAINT disttable_color_unique DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -\set VERBOSITY terse -SELECT * FROM disttable ORDER BY disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 3 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | -(22 rows) - --- ON CONFLICT only works with DO NOTHING for now -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-09 08:13', 7, 3, 27.5) -ON CONFLICT (time) DO UPDATE SET temp = 3.2; -ERROR: ON CONFLICT DO UPDATE not supported on distributed hypertables --- Test that an INSERT that would create a chunk does not work on a --- data node -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) - -ERROR: [db_dist_hypertable_1]: distributed hypertable member cannot create chunk on its own -\set ON_ERROR_STOP 1 --- However, INSERTs on a data node that does not create a chunk works. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE disttable SET "Color" = 4 WHERE "Color" = 3; -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 9 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(23 rows) - -WITH devices AS ( - SELECT DISTINCT device FROM disttable ORDER BY device -) -UPDATE disttable SET "Color" = 2 WHERE device = (SELECT device FROM devices LIMIT 1); -\set ON_ERROR_STOP 0 --- Updates referencing non-existing column -UPDATE disttable SET device = 4 WHERE no_such_column = 2; -ERROR: column "no_such_column" does not exist at character 39 -UPDATE disttable SET no_such_column = 4 WHERE device = 2; -ERROR: column "no_such_column" of relation "disttable" does not exist at character 22 --- Update to system column -UPDATE disttable SET tableoid = 4 WHERE device = 2; -ERROR: cannot assign to system column "tableoid" at character 22 -\set ON_ERROR_STOP 1 --- Test deletes (no rows deleted) -DELETE FROM disttable WHERE device = 3 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | -(3 rows) - -DELETE FROM disttable WHERE time IS NULL; --- Test deletes (rows deleted) -DELETE FROM disttable WHERE device = 4 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 -(1 row) - --- Query to show that rows are deleted -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | 2 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 2 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(19 rows) - --- Ensure rows are deleted on the data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| 2 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| 2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| 2 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -Sun Sep 03 06:09:00 2017 PDT| 1| 2| 2 -(8 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 4 -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Test TRUNCATE -TRUNCATE disttable; --- No data should remain -SELECT * FROM disttable; - time | device | temp | Color -------+--------+------+------- -(0 rows) - --- Metadata and tables cleaned up -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-------------+------------+---------------------+---------+--------+----------- -(0 rows) - -SELECT * FROM show_chunks('disttable'); - show_chunks -------------- -(0 rows) - --- Also cleaned up remotely -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM show_chunks('disttable'); -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- The hypertable view also shows no chunks and no data -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 0 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test underreplicated chunk warning -INSERT INTO underreplicated VALUES ('2017-01-01 06:01', 1, 1.1), - ('2017-01-02 07:01', 2, 3.5); -WARNING: insufficient number of data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+------------------------+---------+------------------------------------------------ - 10 | 2 | _timescaledb_internal | _dist_hyper_2_10_chunk | f | {"time": [1482969600000000, 1483574400000000]} -(1 row) - --- Show chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - --- Show that chunks are created on remote data nodes and that all --- data nodes/chunks have the same data due to replication -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE underreplicated SET temp = 2.0 WHERE device = 2 -RETURNING time, temp, device; - time | temp | device -------------------------------+------+-------- - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - -SELECT * FROM underreplicated; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(2 rows) - --- Show that all replica chunks are updated -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - - remote_exec -------------- - -(1 row) - -DELETE FROM underreplicated WHERE device = 2 -RETURNING *; - time | device | temp -------------------------------+--------+------ - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - --- Ensure deletes across all data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test hypertable creation fails on distributed error -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float); -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_3]: -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float) -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_hypertable('remotetable', 'time', replication_factor => 1); -ERROR: [db_dist_hypertable_3]: relation "remotetable" already exists --- Test distributed_hypertable creation fails with replication factor 0 -CREATE TABLE remotetable2(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_distributed_hypertable('remotetable2', 'time', replication_factor => 0); -WARNING: distributed hypertable is deprecated -ERROR: invalid replication factor -\set ON_ERROR_STOP 1 -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 1 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test distributed hypertable creation with many parameters -\c :TEST_DBNAME :ROLE_SUPERUSER ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE SCHEMA "T3sTSch"; -CREATE SCHEMA "Table\\Schema"; -CREATE SCHEMA "single'schema"; -GRANT ALL ON SCHEMA "T3sTSch" TO :ROLE_1; -GRANT ALL ON SCHEMA "Table\\Schema" TO :ROLE_1; -GRANT ALL ON SCHEMA "single'schema" TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE "Table\\Schema"."Param_Table"("time Col %#^#@$#" timestamptz, __region text, reading float); -SELECT * FROM create_distributed_hypertable('"Table\\Schema"."Param_Table"', 'time Col %#^#@$#', partitioning_column => '__region', -associated_schema_name => 'T3sTSch', associated_table_prefix => 'test*pre_', chunk_time_interval => interval '1 week', -create_default_indexes => FALSE, if_not_exists => TRUE, replication_factor => 2, -data_nodes => ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time Col %#^#@$#" - hypertable_id | schema_name | table_name | created ----------------+---------------+-------------+--------- - 4 | Table\\Schema | Param_Table | t -(1 row) - --- Test detach and attach data node -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, drop_remote_data => true); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 1 - detach_data_node ------------------- - 1 -(1 row) - --- Test attach_data_node. First show dimensions and currently attached --- servers. The number of slices in the space dimension should equal --- the number of servers since we didn't explicitly specify --- number_partitions -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 1 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_3 -(1 row) - -SELECT * FROM attach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" was increased to 2 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 3 | db_dist_hypertable_1 -(1 row) - --- Show updated metadata after attach -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_1 - Param_Table | db_dist_hypertable_3 -(2 rows) - --- Attach another data node but do not auto-repartition, i.e., --- increase the number of slices. -SELECT * FROM attach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', repartition => false); -WARNING: attaching data node is deprecated -WARNING: insufficient number of partitions for dimension "__region" - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 4 | db_dist_hypertable_2 -(1 row) - --- Number of slices should not be increased -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Manually increase the number of partitions -SELECT * FROM set_number_partitions('"Table\\Schema"."Param_Table"', 4); - set_number_partitions ------------------------ - -(1 row) - --- Verify hypertables on all data nodes -SELECT * FROM _timescaledb_catalog.hypertable; - id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compression_state | compressed_hypertable_id | replication_factor | status -----+---------------+-----------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+-------------------+--------------------------+--------------------+-------- - 1 | public | disttable | _timescaledb_internal | _dist_hyper_1 | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 1 | 0 - 2 | public | underreplicated | _timescaledb_internal | _dist_hyper_2 | 1 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 4 | 0 - 4 | Table\\Schema | Param_Table | T3sTSch | test*pre_ | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 2 | 0 -(3 rows) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+--------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 4 | _timescaledb_functions | get_partition_hash | | | | -(5 rows) - -SELECT * FROM test.show_triggers('"Table\\Schema"."Param_Table"'); - Trigger | Type | Function --------------------+------+--------------------------------------- - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.hypertable; -SELECT * FROM _timescaledb_catalog.dimension; -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_1]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_1]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_2]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 4|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_2]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_3]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_3]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - - remote_exec -------------- - -(1 row) - --- Verify that repartitioning works as expected on detach_data_node -SELECT * FROM detach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"', repartition => true); -WARNING: detaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 2 - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, repartition => false); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Test multi-dimensional hypertable. The add_dimension() command --- should be propagated to backends. -CREATE TABLE dimented_table (time timestamptz, column1 int, column2 timestamptz, column3 int); -SELECT * FROM create_distributed_hypertable('dimented_table', 'time', partitioning_column => 'column1', number_partitions => 4, replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1']); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 5 | public | dimented_table | t -(1 row) - --- Create one chunk to block add_dimension -INSERT INTO dimented_table VALUES('2017-01-01 06:01', 1, '2017-01-01 08:01', 1); -CREATE VIEW dimented_table_slices AS -SELECT c.id AS chunk_id, c.hypertable_id, ds.dimension_id, cc.dimension_slice_id, c.schema_name AS - chunk_schema, c.table_name AS chunk_table, ds.range_start, ds.range_end -FROM _timescaledb_catalog.chunk c -INNER JOIN _timescaledb_catalog.hypertable h ON (c.hypertable_id = h.id) -INNER JOIN _timescaledb_catalog.dimension td ON (h.id = td.hypertable_id) -INNER JOIN _timescaledb_catalog.dimension_slice ds ON (ds.dimension_id = td.id) -INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.dimension_slice_id = ds.id AND cc.chunk_id = c.id) -WHERE h.table_name = 'dimented_table' -ORDER BY c.id, ds.dimension_id; -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+------------------ - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 -(2 rows) - --- add_dimension() with existing data -SELECT * FROM add_dimension('dimented_table', 'column2', chunk_time_interval => interval '1 week'); -NOTICE: adding not-null constraint to column "column2" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 9 | public | dimented_table | column2 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(3 rows) - -SELECT * FROM add_dimension('dimented_table', 'column3', 4, partitioning_func => '_timescaledb_functions.get_partition_for_key'); - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 10 | public | dimented_table | column3 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 - 11 | 5 | 10 | 11 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(4 rows) - -SELECT * FROM dimented_table ORDER BY time; - time | column1 | column2 | column3 -------------------------------+---------+------------------------------+--------- - Sun Jan 01 06:01:00 2017 PST | 1 | Sun Jan 01 08:01:00 2017 PST | 1 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - -SELECT * FROM attach_data_node(:'DATA_NODE_2', 'dimented_table'); -WARNING: attaching data node is deprecated - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 5 | 5 | db_dist_hypertable_2 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - --- ensure data node has new dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.dimension; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time |timestamp with time zone|t | | | | 604800000000| | | - 7| 4|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 4|column2 |timestamp with time zone|t | | | | 604800000000| | | - 9| 4|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 5|time |timestamp with time zone|t | | | | 604800000000| | | - 9| 5|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | -10| 5|column2 |timestamp with time zone|t | | | | 604800000000| | | -11| 5|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - - remote_exec -------------- - -(1 row) - ---test per-data node queries --- Create some chunks through insertion -CREATE TABLE disttable_replicated(time timestamptz PRIMARY KEY, device int CHECK (device > 0), temp float, "Color" int); -SELECT * FROM create_hypertable('disttable_replicated', 'time', replication_factor => 2); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------------+--------- - 6 | public | disttable_replicated | t -(1 row) - -INSERT INTO disttable_replicated VALUES - ('2017-01-01 06:01', 1, 1.1, 1), - ('2017-01-01 08:01', 1, 1.2, 2), - ('2018-01-02 08:01', 2, 1.3, 3), - ('2019-01-01 09:11', 3, 2.1, 4), - ('2020-01-01 06:01', 5, 1.1, 10), - ('2020-01-01 08:01', 6, 1.2, 11), - ('2021-01-02 08:01', 7, 1.3, 12), - ('2022-01-01 09:11', 8, 2.1, 13); -SELECT * FROM disttable_replicated; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Wed Jan 01 06:01:00 2020 PST | 5 | 1.1 | 10 - Wed Jan 01 08:01:00 2020 PST | 6 | 1.2 | 11 - Tue Jan 02 08:01:00 2018 PST | 2 | 1.3 | 3 - Sat Jan 02 08:01:00 2021 PST | 7 | 1.3 | 12 - Tue Jan 01 09:11:00 2019 PST | 3 | 2.1 | 4 - Sat Jan 01 09:11:00 2022 PST | 8 | 2.1 | 13 -(8 rows) - -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---guc disables the optimization -SET timescaledb.enable_per_data_node_queries = FALSE; -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Append (actual rows=8 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_12_chunk."time", _dist_hyper_6_12_chunk.device, _dist_hyper_6_12_chunk.temp, _dist_hyper_6_12_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_12_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_13_chunk."time", _dist_hyper_6_13_chunk.device, _dist_hyper_6_13_chunk.temp, _dist_hyper_6_13_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_13_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_14_chunk."time", _dist_hyper_6_14_chunk.device, _dist_hyper_6_14_chunk.temp, _dist_hyper_6_14_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_14_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_15_chunk."time", _dist_hyper_6_15_chunk.device, _dist_hyper_6_15_chunk.temp, _dist_hyper_6_15_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_15_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_16_chunk."time", _dist_hyper_6_16_chunk.device, _dist_hyper_6_16_chunk.temp, _dist_hyper_6_16_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_16_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_17_chunk."time", _dist_hyper_6_17_chunk.device, _dist_hyper_6_17_chunk.temp, _dist_hyper_6_17_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_17_chunk -(31 rows) - -SET timescaledb.enable_per_data_node_queries = TRUE; ---test WHERE clause -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=0 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) -(21 rows) - ---test OR -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0 or "Color" = 11; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=3 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=3 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=1 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) -(21 rows) - ---test some chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2018-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=2 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) -(15 rows) - ---test all chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2002-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=0 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - One-Time Filter: false -(3 rows) - ---test cte -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH cte AS ( - SELECT * FROM disttable_replicated -) -SELECT * FROM cte; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---queries that involve updates/inserts are not optimized -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH devices AS ( - SELECT DISTINCT device FROM disttable_replicated ORDER BY device -) -UPDATE disttable_replicated SET device = 2 WHERE device = (SELECT device FROM devices LIMIT 1); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Update on public.disttable_replicated (actual rows=0 loops=1) - Update on public.disttable_replicated disttable_replicated_1 - Foreign Update on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_12_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_3 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_13_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_4 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_14_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_5 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_15_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_6 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_16_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_7 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_17_chunk SET device = $2 WHERE ctid = $1 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Unique (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_replicated_9.device - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_9 (actual rows=1 loops=1) - Output: disttable_replicated_9.device - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_10 (actual rows=1 loops=1) - Output: disttable_replicated_10.device - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_11 (actual rows=1 loops=1) - Output: disttable_replicated_11.device - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Result (actual rows=2 loops=1) - Output: 2, disttable_replicated.tableoid, disttable_replicated.ctid, (NULL::record) - -> Append (actual rows=2 loops=1) - -> Seq Scan on public.disttable_replicated disttable_replicated_1 (actual rows=0 loops=1) - Output: disttable_replicated_1.tableoid, disttable_replicated_1.ctid, NULL::record - Filter: (disttable_replicated_1.device = $0) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2.tableoid, disttable_replicated_2.ctid, disttable_replicated_2.* - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_12_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_3 (actual rows=0 loops=1) - Output: disttable_replicated_3.tableoid, disttable_replicated_3.ctid, disttable_replicated_3.* - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_13_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_4 (actual rows=0 loops=1) - Output: disttable_replicated_4.tableoid, disttable_replicated_4.ctid, disttable_replicated_4.* - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_14_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_5 (actual rows=0 loops=1) - Output: disttable_replicated_5.tableoid, disttable_replicated_5.ctid, disttable_replicated_5.* - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_15_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_6 (actual rows=0 loops=1) - Output: disttable_replicated_6.tableoid, disttable_replicated_6.ctid, disttable_replicated_6.* - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_16_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_7 (actual rows=0 loops=1) - Output: disttable_replicated_7.tableoid, disttable_replicated_7.ctid, disttable_replicated_7.* - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_17_chunk WHERE ((device = $1::integer)) -(77 rows) - --- Test inserts with smaller batch size and more tuples to reach full --- batch -SET timescaledb.max_insert_batch_size=4; -CREATE TABLE twodim (time timestamptz DEFAULT '2019-02-10 10:11', "Color" int DEFAULT 11 CHECK ("Color" > 0), temp float DEFAULT 22.1); --- Create a replicated table to ensure we handle that case correctly --- with batching -SELECT * FROM create_hypertable('twodim', 'time', 'Color', 3, replication_factor => 2, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2',:'DATA_NODE_3']); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 7 | public | twodim | t -(1 row) - -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------+-------+------ -(0 rows) - --- INSERT enough data to stretch across multiple batches per --- data node. Also return a system column. Although we write tuples to --- multiple data nodes, the returned tuple should only be the ones in the --- original insert statement (without the replica tuples). -WITH result AS ( - INSERT INTO twodim VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1) - RETURNING tableoid = 'twodim'::regclass AS is_tableoid, time, temp, "Color" -) SELECT * FROM result ORDER BY time; - is_tableoid | time | temp | Color --------------+------------------------------+------+------- - t | Wed Feb 01 06:01:00 2017 PST | 1.1 | 1 - t | Wed Feb 01 08:01:00 2017 PST | 1.2 | 1 - t | Fri Feb 02 08:01:00 2018 PST | 1.3 | 2 - t | Fri Feb 01 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 10:01:00 2019 PST | 1.2 | 5 - t | Sun Feb 03 11:11:00 2019 PST | 3.5 | 6 - t | Mon Feb 04 08:21:00 2019 PST | 6.6 | 4 - t | Mon Feb 04 10:11:00 2019 PST | 7.4 | 7 - t | Mon Feb 04 12:11:00 2019 PST | 2.1 | 8 - t | Tue Feb 05 13:31:00 2019 PST | 6.3 | 8 - t | Wed Feb 06 01:13:00 2019 PST | 7.9 | 7 - t | Wed Feb 06 02:11:00 2019 PST | 1.8 | 5 - t | Wed Feb 06 19:24:00 2019 PST | 5.9 | 9 - t | Thu Feb 07 09:33:00 2019 PST | 9.5 | 7 - t | Thu Feb 07 18:44:00 2019 PST | 9.7 | 5 - t | Thu Feb 07 20:24:00 2019 PST | | 6 - t | Fri Feb 08 08:54:00 2019 PST | 7.3 | 1 - t | Fri Feb 08 18:14:00 2019 PST | 8.2 | 4 - t | Sat Feb 09 19:23:00 2019 PST | 9.1 | 8 -(20 rows) - --- Test insert with default values and a batch size of 1. -SET timescaledb.max_insert_batch_size=1; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim DEFAULT VALUES; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - Batch size: 1 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - -> Result - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision -(12 rows) - -INSERT INTO twodim DEFAULT VALUES; --- Reset the batch size -SET timescaledb.max_insert_batch_size=4; --- Constraint violation error check --- --- Execute and filter mentioned data node name in the error message. -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ INSERT INTO twodim VALUES ('2019-02-10 17:54', 0, 10.2) $$, :'TEST_DBNAME'); -ERROR: [db_dist_hypertable_x]: new row for relation "_dist_hyper_7_23_chunk" violates check constraint "twodim_Color_check" -\set ON_ERROR_STOP 1 --- Disable batching, reverting to FDW tuple-by-tuple inserts. --- First EXPLAIN with batching turned on. -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - Batch size: 4 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3), ..., ($10, $11, $12) - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(12 rows) - -SET timescaledb.max_insert_batch_size=0; --- Compare without batching -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Insert on public.twodim - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(9 rows) - --- Insert without batching -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when multiple dimensions are involved. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT * FROM twodim -ORDER BY time; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: twodim."time", twodim."Color", twodim.temp - -> Merge Append - Sort Key: twodim_1."time" - -> Custom Scan (DataNodeScan) on public.twodim twodim_1 - Output: twodim_1."time", twodim_1."Color", twodim_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_7_18_chunk, _dist_hyper_7_22_chunk, _dist_hyper_7_25_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12, 14]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_18_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_18_chunk - Output: _dist_hyper_7_18_chunk."time", _dist_hyper_7_18_chunk."Color", _dist_hyper_7_18_chunk.temp - -> Index Scan Backward using _dist_hyper_7_22_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_22_chunk - Output: _dist_hyper_7_22_chunk."time", _dist_hyper_7_22_chunk."Color", _dist_hyper_7_22_chunk.temp - -> Index Scan Backward using _dist_hyper_7_25_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_25_chunk - Output: _dist_hyper_7_25_chunk."time", _dist_hyper_7_25_chunk."Color", _dist_hyper_7_25_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_2 - Output: twodim_2."time", twodim_2."Color", twodim_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_7_19_chunk, _dist_hyper_7_21_chunk, _dist_hyper_7_24_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 11, 13]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_19_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_19_chunk - Output: _dist_hyper_7_19_chunk."time", _dist_hyper_7_19_chunk."Color", _dist_hyper_7_19_chunk.temp - -> Index Scan Backward using _dist_hyper_7_21_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_21_chunk - Output: _dist_hyper_7_21_chunk."time", _dist_hyper_7_21_chunk."Color", _dist_hyper_7_21_chunk.temp - -> Index Scan Backward using _dist_hyper_7_24_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_24_chunk - Output: _dist_hyper_7_24_chunk."time", _dist_hyper_7_24_chunk."Color", _dist_hyper_7_24_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_3 - Output: twodim_3."time", twodim_3."Color", twodim_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_7_20_chunk, _dist_hyper_7_23_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_20_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_20_chunk - Output: _dist_hyper_7_20_chunk."time", _dist_hyper_7_20_chunk."Color", _dist_hyper_7_20_chunk.temp - -> Index Scan Backward using _dist_hyper_7_23_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_23_chunk - Output: _dist_hyper_7_23_chunk."time", _dist_hyper_7_23_chunk."Color", _dist_hyper_7_23_chunk.temp - -(56 rows) - -SET timescaledb.enable_remote_explain = OFF; --- Check results -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------------------------------+-------+------ - Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - Thu Feb 07 20:24:00 2019 PST | 6 | - Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 - Sun Feb 10 10:11:00 2019 PST | 11 | 22.1 - Sun Feb 10 16:23:00 2019 PST | 5 | 7.1 - Sun Feb 10 17:11:00 2019 PST | 7 | 3.2 -(23 rows) - -SELECT count(*) FROM twodim; - count -------- - 23 -(1 row) - --- Show distribution across data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM twodim -ORDER BY time; -SELECT count(*) FROM twodim; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_1]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -(12 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_1]: -count ------ - 12 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_2]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(19 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_2]: -count ------ - 19 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_3]: -time |Color|temp -----------------------------+-----+---- -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(15 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_3]: -count ------ - 15 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Distributed table with custom type that has no binary output -CREATE TABLE disttable_with_ct(time timestamptz, txn_id rxid, val float, info text); -SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 2); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------------+--------- - 8 | public | disttable_with_ct | t -(1 row) - --- Insert data with custom type -INSERT INTO disttable_with_ct VALUES - ('2019-01-01 01:01', 'ts-1-10-20-30', 1.1, 'a'), - ('2019-01-01 01:02', 'ts-1-11-20-30', 2.0, repeat('abc', 1000000)); -- TOAST --- Test queries on distributed table with custom type -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - -SET timescaledb.enable_connection_binary_data=false; -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - --- Test DELETE with replication -DELETE FROM disttable_with_ct WHERE info = 'a'; --- Check if row is gone -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(1 row) - --- Connect to data nodes to see if data is gone -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_1]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_2]: -time|txn_id|val|substring -----+------+---+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_3]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test single quote in names -SET SCHEMA 'single''schema'; -CREATE TABLE "disttable'quote"(time timestamptz, "device'quote" int, val float, info text); -SELECT public.create_distributed_hypertable( - 'disttable''quote', 'time', 'device''quote', data_nodes => ARRAY[:'DATA_NODE_1'] -); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------------- - (9,single'schema,disttable'quote,t) -(1 row) - -SET SCHEMA 'public'; -CREATE TABLE disttable_drop_chunks(time timestamptz, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable_drop_chunks', 'time', 'device', number_partitions => 3, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------------+--------- - 10 | public | disttable_drop_chunks | t -(1 row) - -INSERT INTO disttable_drop_chunks VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5); --- Show chunks on access node -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 27 | 10 | _timescaledb_internal | _dist_hyper_10_27_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 28 | 10 | _timescaledb_internal | _dist_hyper_10_28_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 29 | 10 | _timescaledb_internal | _dist_hyper_10_29_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show chunks on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 16| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 17| 9|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 16| 9|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 7|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 16| 7|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM drop_chunks('disttable_drop_chunks', older_than => '2018-01-01'::timestamptz); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_27_chunk - _timescaledb_internal._dist_hyper_10_28_chunk - _timescaledb_internal._dist_hyper_10_29_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------------------------------+--------+------- - Mon Jul 02 08:01:00 2018 PDT | 87 | 2 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1 - Sun Jul 01 09:11:00 2018 PDT | 90 | 3 - Sun Jul 01 08:01:00 2018 PDT | 29 | 2 -(4 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- test passing newer_than as interval -SELECT * FROM drop_chunks('disttable_drop_chunks', newer_than => interval '10 years'); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_30_chunk - _timescaledb_internal._dist_hyper_10_31_chunk - _timescaledb_internal._dist_hyper_10_32_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------+--------+------- -(0 rows) - -CREATE TABLE "weird nAme\\#^."(time bigint, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('"weird nAme\\#^."', 'time', 'device', 3, chunk_time_interval => 100, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 11 | public | weird nAme\\#^. | t -(1 row) - -INSERT INTO "weird nAme\\#^." VALUES - (300, 1, 1.1), - (400, 3, 2.1), - (350, 1, 1.2); -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- - 300 | 1 | 1 - 350 | 1 | 1 - 400 | 3 | 2 -(3 rows) - --- drop chunks using bigint as time -SELECT * FROM drop_chunks('"weird nAme\\#^."', older_than => 1000); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_33_chunk - _timescaledb_internal._dist_hyper_11_34_chunk -(2 rows) - -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- -(0 rows) - ------------------------------------------------------------------------------------------ --- Test that settings on hypertables are distributed to data nodes ------------------------------------------------------------------------------------------ -DROP TABLE disttable CASCADE; -CREATE TABLE disttable (time bigint, device int, temp float); -SELECT create_distributed_hypertable('disttable', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (12,public,disttable,t) -(1 row) - --- Show the dimension configuration on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -14| 9|time |bigint |t | | | | 1000000| | | -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test adding a space dimension. Should apply to data nodes as --- well. We're setting num_partitions lower than the number of servers --- and expect a warning. -SELECT * FROM add_dimension('disttable', 'device', 1, partitioning_func => '_timescaledb_functions.get_partition_hash'); -WARNING: insufficient number of partitions for dimension "device" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+------------+-------------+--------- - 22 | public | disttable | device | t -(1 row) - -CREATE INDEX disttable_device_time_idx ON disttable (device, time); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 1000000| | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Show that changing dimension settings apply to data nodes -SELECT * FROM set_chunk_time_interval('disttable', 2000000000::bigint); - set_chunk_time_interval -------------------------- - -(1 row) - -SELECT * FROM set_number_partitions('disttable', 3); - set_number_partitions ------------------------ - -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT' -$$); -SELECT * FROM set_integer_now_func('disttable', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - --- Show changes to dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Tests for using tablespaces with distributed hypertables -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE TABLESPACE :TABLESPACE_1 OWNER :ROLE_1 LOCATION :'spc1path'; -CREATE TABLESPACE :TABLESPACE_2 OWNER :ROLE_1 LOCATION :'spc2path'; -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: tablespace "db_dist_hypertable_1" is not attached to hypertable "disttable" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable'); - detach_tablespaces --------------------- - 0 -(1 row) - --- Continue to use previously attached tablespace, but block attach/detach -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_distributed_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (13,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_13_35_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable2'); - detach_tablespaces --------------------- - 0 -(1 row) - -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - --- Ensure tablespace API works for data nodes -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT detach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec($$ -SELECT detach_tablespaces('disttable2'); -$$); -DROP TABLE disttable2; -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint, replication_factor => 1); -NOTICE: adding not-null constraint to column "time" - create_hypertable --------------------------- - (14,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_14_36_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - -DROP TABLE disttable2; -DROP TABLESPACE :TABLESPACE_1; -DROP TABLESPACE :TABLESPACE_2; --- Make sure table qualified name is used in chunks_in function. Otherwise having a table name same as a column name might yield an error -CREATE TABLE dist_device(time timestamptz, dist_device int, temp float); -SELECT * FROM create_distributed_hypertable('dist_device', 'time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 15 | public | dist_device | t -(1 row) - -INSERT INTO dist_device VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2); -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM dist_device; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) -(5 rows) - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when only time partitioning is being used. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT "time", dist_device, temp FROM public.dist_device ORDER BY "time" ASC NULLS LAST; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Index Scan Backward using _dist_hyper_15_37_chunk_dist_device_time_idx on _timescaledb_internal._dist_hyper_15_37_chunk - Output: _dist_hyper_15_37_chunk."time", _dist_hyper_15_37_chunk.dist_device, _dist_hyper_15_37_chunk.temp - -(9 rows) - -SELECT * FROM dist_device; - time | dist_device | temp -------------------------------+-------------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 -(3 rows) - --- Test estimating relation size without stats -CREATE TABLE hyper_estimate(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('hyper_estimate', 'time', 'device', number_partitions => 3, replication_factor => 1, chunk_time_interval => INTERVAL '7 days'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 16 | public | hyper_estimate | t -(1 row) - --- This will enable us to more easily see estimates per chunk -SET timescaledb.enable_per_data_node_queries = false; --- Estimating chunk progress uses current timestamp so we override it for test purposes -SELECT test.tsl_override_current_timestamptz('2017-11-11 00:00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - --- Test estimates when backfilling. 3 chunks should be historical and 3 should be considered current when estimating. --- Note that estimate numbers are way off since we are using shared buffer size as starting point. This will not be --- an issue in 'production' like env since chunk size should be similar to shared buffer size. -INSERT INTO hyper_estimate VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); --- This will calculate the stats -ANALYZE hyper_estimate; -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..60021.38 rows=15 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) -(7 rows) - --- Let's insert data into a new chunk. This will result in chunk creation. -INSERT INTO hyper_estimate VALUES ('2019-11-11 06:01', 1, 1.1); --- We have stats for previous chunks so we can interpolate number of rows for the new chunk -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..70023.31 rows=17 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) - -> Foreign Scan on _dist_hyper_16_44_chunk (cost=10000.00..10001.93 rows=2 width=20) -(8 rows) - -CREATE TABLE devices ( - device_id INTEGER PRIMARY KEY, - device_name VARCHAR(10) -); -CALL distributed_exec($$ - CREATE TABLE devices(device_id INTEGER PRIMARY KEY, device_name VARCHAR(10)) -$$); -INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765'); -CALL distributed_exec($$ - INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765') -$$); -CREATE TABLE hyper ( - time TIMESTAMPTZ NOT NULL, - device INTEGER REFERENCES devices(device_id), - temp FLOAT -); -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours' -); -WARNING: distributed hypertable is deprecated -WARNING: distributed hypertable "hyper" has a foreign key to a non-distributed table - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 17 | public | hyper | t -(1 row) - --- Inserting some values should succeed. -INSERT INTO hyper VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM hyper -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 1 | 1.65 - Mon Jan 02 04:00:00 2017 PST | 2 | 1.4 - Mon Jan 02 07:00:00 2017 PST | 1 | 1.3 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.6 - Tue Jan 03 01:00:00 2017 PST | 3 | 3 - Sat Jan 13 01:00:00 2018 PST | 2 | 1.4 - Sat Jan 13 04:00:00 2018 PST | 2 | 3 - Sat Jan 13 16:00:00 2018 PST | 3 | 2 -(8 rows) - --- Add some devices on the access node only. Inserts should then fail. -INSERT INTO devices VALUES (6, 'E999'); -\set ON_ERROR_STOP 0 -INSERT INTO hyper VALUES ('2017-01-01 06:01', 6, 1.1); -ERROR: [db_dist_hypertable_1]: insert or update on table "_dist_hyper_17_45_chunk" violates foreign key constraint "26_17_hyper_device_fkey" -\set ON_ERROR_STOP 1 --- Test alter replication factor with data -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Dimension partitions should be updated to account for replication --- to additional data nodes -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1} - hyper | 29 | 715827882 | {db_dist_hypertable_2} - hyper | 29 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -SELECT * FROM set_replication_factor('hyper', 3); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------------------------------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3,db_dist_hypertable_1} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1,db_dist_hypertable_2} -(3 rows) - -INSERT INTO hyper VALUES ('2017-01-02 07:11', 1, 1.7); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-02-01 06:01', 1, 5.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------------------------------------- - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1} -(3 rows) - -INSERT INTO hyper VALUES ('2017-03-01 06:01', 1, 15.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', replication_factor => 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-04-01 06:01', 2, 45.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 14|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('hyper', replication_factor => 4); -ERROR: replication factor too large for hypertable "hyper" -\set ON_ERROR_STOP 1 -DROP TABLE hyper; -CALL distributed_exec($$ - DROP TABLE devices; -$$); -DROP TABLE devices; --- Test storage options are distributed to data nodes --- --- Make sure that options used during CREATE TABLE WITH and CREATE INDEX WITH --- are properly distributed. --- -CREATE TABLE disttable_with_relopts_1(time timestamptz NOT NULL, device int) WITH (fillfactor=10); -CREATE TABLE disttable_with_relopts_2(time timestamptz NOT NULL, device int) WITH (fillfactor=10, parallel_workers=1); -CREATE TABLE disttable_with_relopts_3(time timestamptz NOT NULL, device int); -CREATE INDEX disttable_with_relopts_3_idx ON disttable_with_relopts_3(device) WITH (fillfactor=20); -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_1', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 18 | public | disttable_with_relopts_1 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_2', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 19 | public | disttable_with_relopts_2 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_3', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 20 | public | disttable_with_relopts_3 | t -(1 row) - -INSERT INTO disttable_with_relopts_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -INSERT INTO disttable_with_relopts_2 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=10} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; - relname | reloptions ---------------------------+------------------------------------ - disttable_with_relopts_2 | {fillfactor=10,parallel_workers=1} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_3 | -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; - relname | reloptions -------------------------------+----------------- - disttable_with_relopts_3_idx | {fillfactor=20} -(1 row) - --- Ensure reloptions are not set for distributed hypertable chunks on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_19_57_chunk | - _dist_hyper_19_58_chunk | -(2 rows) - --- Ensure parent tables has proper storage options -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Ensure index has proper storage options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Make sure chunks derive parent reloptions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname|reloptions --------+---------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_57_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_58_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- ALTER TABLE SET/RESET support for distributed hypertable --- --- SET -ALTER TABLE disttable_with_relopts_1 SET (fillfactor=40); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=40} -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- RESET -ALTER TABLE disttable_with_relopts_1 RESET (fillfactor); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_1 | -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_55_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_56_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_with_relopts_1; -DROP TABLE disttable_with_relopts_2; -DROP TABLE disttable_with_relopts_3; --- Test SERIAL type column support for distributed hypertables --- -CREATE TABLE disttable_serial(time timestamptz NOT NULL, device int, id1 SERIAL, id2 SMALLSERIAL, id3 BIGSERIAL); -SELECT create_distributed_hypertable('disttable_serial', 'time', 'device'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (21,public,disttable_serial,t) -(1 row) - --- Show created columns (AN and DN tables must be exact) -SELECT * FROM test.show_columns('disttable_serial'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | f - id1 | integer | t - id2 | smallint | t - id3 | bigint | t -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * FROM test.show_columns('disttable_serial'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_1]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_2]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_3]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure DEFAULT expression is applied on the AN only -SELECT column_name, column_default -FROM information_schema.columns -WHERE table_name = 'disttable_serial'; - column_name | column_default --------------+----------------------------------------------- - time | - device | - id1 | nextval('disttable_serial_id1_seq'::regclass) - id2 | nextval('disttable_serial_id2_seq'::regclass) - id3 | nextval('disttable_serial_id3_seq'::regclass) -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_1]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_2]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_3]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure sequences were created on the AN only -INSERT INTO disttable_serial VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT currval('disttable_serial_id1_seq'::regclass), - currval('disttable_serial_id2_seq'::regclass), - currval('disttable_serial_id3_seq'::regclass); - currval | currval | currval ----------+---------+--------- - 5 | 5 | 5 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT currval('disttable_serial_id1_seq'::regclass); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT currval('disttable_serial_id1_seq'::regclass) -ERROR: [db_dist_hypertable_1]: relation "disttable_serial_id1_seq" does not exist -\set ON_ERROR_STOP 1 --- Verify that the data is getting spread over multiple data nodes with the --- serial values being set correctly -SELECT * from disttable_serial ORDER BY id1; - time | device | id1 | id2 | id3 -------------------------------+--------+-----+-----+----- - Sun Jan 01 06:01:00 2017 PST | 1 | 1 | 1 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2 | 2 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 3 | 3 | 3 - Mon Jan 02 08:01:00 2017 PST | 2 | 4 | 4 | 4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 5 | 5 | 5 -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * from disttable_serial ORDER BY id1; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_1]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 06:01:00 2017 PST| 1| 1| 1| 1 -Sun Jan 01 08:01:00 2017 PST| 1| 3| 3| 3 -Mon Jul 02 08:01:00 2018 PDT| 87| 5| 5| 5 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_2]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Mon Jan 02 08:01:00 2017 PST| 2| 4| 4| 4 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_3]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 09:11:00 2017 PST| 3| 2| 2| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_serial; --- Test insert batching case which will hit the limit of arguments for --- prepared statements (65k). --- --- Issue: #1702 --- distributed hypertable insert fails when # of columns are more than 65 --- --- Use default value -SET timescaledb.max_insert_batch_size TO 1000; -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int , - dummy6 int , - dummy7 int , - dummy8 int , - dummy9 int , - dummy10 int , - dummy11 int , - dummy12 int , - dummy13 int , - dummy14 int , - dummy15 int , - dummy16 int , - dummy17 int , - dummy18 int , - dummy19 int , - dummy20 int , - dummy21 int , - dummy22 int , - dummy23 int , - dummy24 int , - dummy25 int , - dummy26 int , - dummy27 int , - dummy28 int , - dummy29 int , - dummy30 int , - dummy31 int , - dummy32 int , - dummy33 int , - dummy34 int , - dummy35 int , - dummy36 int , - dummy37 int , - dummy38 int , - dummy39 int , - dummy40 int , - dummy41 int , - dummy42 int , - dummy43 int , - dummy44 int , - dummy45 int , - dummy46 int , - dummy47 int , - dummy48 int , - dummy49 int , - dummy50 int , - dummy51 int , - dummy52 int , - dummy53 int , - dummy54 int , - dummy55 int , - dummy56 int , - dummy57 int , - dummy58 int , - dummy59 int , - dummy60 int , - dummy61 int , - dummy62 int , - dummy63 int , - dummy64 int , - dummy65 int , - dummy66 int , - dummy67 int , - dummy68 int , - dummy69 int , - dummy70 int , - dummy71 int -); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (22,public,test_1702,t) -(1 row) - --- Original issue case --- --- Expect batch size to be lower than defined max_insert_batch_size --- -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; - QUERY PLAN ------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> ProjectSet - -> Result -(9 rows) - -INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; -SELECT count(*) from test_1702; - count -------- - 1500 -(1 row) - -DROP TABLE test_1702; --- --- Expect batch size to be similair to max_insert_batch_size --- -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int - ); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (23,public,test_1702,t) -(1 row) - -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -DROP TABLE test_1702; --- --- Test that creating a hypertable with a space dimension and --- if_not_exists works as expected, that is, the second call does not --- generate an error (and does not crash). --- -CREATE TABLE whatever ( - timestamp TIMESTAMPTZ NOT NULL, - user_id INT NOT NULL, - data JSONB -); -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | t -(1 row) - --- Check the hypertable sequence before and after call to ensure that --- the hypertable sequence was not increased with the second call. -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -NOTICE: table "whatever" is already a hypertable, skipping - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | f -(1 row) - -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - --- Test that creating a distributed hypertable from a table with data --- fails, and that migrate_data blocked. -CREATE TABLE dist_hypertable_1 ( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temp FLOAT -); -INSERT INTO dist_hypertable_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => FALSE); -WARNING: distributed hypertable is deprecated -ERROR: table "dist_hypertable_1" is not empty -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => TRUE); -WARNING: distributed hypertable is deprecated -ERROR: cannot migrate data for distributed hypertable -\set ON_ERROR_STOP 1 --- Test creating index with transaction per chunk on a distributed hypertable --- -DROP TABLE disttable; -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 25 | public | disttable | t -(1 row) - -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -\set ON_ERROR_STOP 0 -CREATE INDEX disttable_time_device_idx ON disttable (time, device) WITH (timescaledb.transaction_per_chunk); -ERROR: cannot use timescaledb.transaction_per_chunk with distributed hypertable -\set ON_ERROR_STOP 1 --- Test using system columns with distributed hypertable --- -CREATE TABLE dist_syscol(time timestamptz NOT NULL, color int, temp float); -SELECT * FROM create_distributed_hypertable('dist_syscol', 'time', 'color'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 26 | public | dist_syscol | t -(1 row) - -INSERT INTO dist_syscol VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1); --- Return chunk table as a source -SET timescaledb.enable_per_data_node_queries = false; -SELECT tableoid::regclass, * FROM dist_syscol; - tableoid | time | color | temp ------------------------------------------------+------------------------------+-------+------ - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - _timescaledb_internal._dist_hyper_26_73_chunk | Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - _timescaledb_internal._dist_hyper_26_74_chunk | Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_74_chunk | Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_75_chunk | Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - _timescaledb_internal._dist_hyper_26_76_chunk | Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - _timescaledb_internal._dist_hyper_26_76_chunk | Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - _timescaledb_internal._dist_hyper_26_76_chunk | Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - _timescaledb_internal._dist_hyper_26_77_chunk | Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - _timescaledb_internal._dist_hyper_26_78_chunk | Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - _timescaledb_internal._dist_hyper_26_79_chunk | Thu Feb 07 20:24:00 2019 PST | 6 | - _timescaledb_internal._dist_hyper_26_79_chunk | Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - _timescaledb_internal._dist_hyper_26_79_chunk | Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 -(20 rows) - --- Produce an error -SET timescaledb.enable_per_data_node_queries = true; -\set ON_ERROR_STOP 0 -SELECT tableoid::regclass, * FROM dist_syscol; -ERROR: system columns are not accessible on distributed hypertables with current settings -\set ON_ERROR_STOP 1 ------------------------ --- Test DataNodeCopy -- ------------------------ -SET timescaledb.enable_distributed_insert_with_copy=true; -DROP TABLE disttable; --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with DataNodeCopy -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 27 | public | disttable | t -(1 row) - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -CREATE TYPE highlow AS (high int, low int); -CALL distributed_exec($$ CREATE TYPE highlow AS (high int, low int) $$); -ALTER TABLE datatable ADD COLUMN minmaxes highlow[]; -INSERT INTO datatable (id, time, device, temp_c, minmaxes) VALUES - (1, '2017-01-01 06:01', 1, 1.2, ARRAY[(1,2)::highlow]), - (2, '2017-01-01 09:11', 3, 4.3, ARRAY[(2,3)::highlow]), - (3, '2017-01-01 08:01', 1, 7.3, ARRAY[(4,5)::highlow]), - (4, '2017-01-02 08:01', 2, 0.23, ARRAY[(6,7)::highlow]), - (5, '2018-07-02 08:01', 87, 0.0, ARRAY[(8,9)::highlow]), - (6, '2018-07-01 06:01', 13, 3.1, ARRAY[(10,11)::highlow]), - (7, '2018-07-01 09:11', 90, 10303.12, ARRAY[(12,13)::highlow]), - (8, '2018-07-01 08:01', 29, 64, ARRAY[(14,15)::highlow]); --- Show that DataNodeCopy is used instead of DataNodeDispatch. Should --- default to FORMAT binary in the remote SQL. Add RETURNING to show --- that it works. -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Remote SQL: COPY public.disttable (id, "time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(13 rows) - --- Perform the actual insert -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - --- Show that the data was added: -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - -SELECT count(*) FROM disttable; - count -------- - 8 -(1 row) - --- Add an array of a composite type to check that DataNodeCopy --- switches to text format if we use a table with an array of a custom --- type. There should be no "FORMAT binary" in the remote explain. -ALTER TABLE disttable ADD COLUMN minmaxes highlow[]; -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=56) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=56) - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - Remote SQL: COPY public.disttable (id, "time", device, temp_c, minmaxes) FROM STDIN - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=56) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes -(11 rows) - -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; --- Should have double amount of rows compared to before and half of --- them values in the new column. Note, must use TEXT format on the --- connection to make query work with custom type array. -SET timescaledb.enable_connection_binary_data=false; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -SELECT count(*) FROM disttable; - count -------- - 16 -(1 row) - --- Binary format should lead to data incompatibility in PG 13 and earlier, --- because the highlow data type has different oids on data and access nodes. --- Use this to test the deserialization error reporting. Newer PG version --- ignore this oid mismatch for non-builtin types. -SET timescaledb.enable_connection_binary_data=true; -\set ON_ERROR_STOP 0 -SET timescaledb.remote_data_fetcher = 'copy'; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -SET timescaledb.remote_data_fetcher = 'cursor'; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -\set ON_ERROR_STOP 1 -RESET timescaledb.remote_data_fetcher; --- Show that DataNodeCopy is NOT used when source hypertable and target hypertable --- of the SELECT are both distributed. Try subselects with LIMIT, RETURNING and --- different distributed hypertable as source -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(10 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable LIMIT 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> Limit - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(13 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(10 rows) - -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; -INSERT INTO disttable (time, device, temp_c) -SELECT * FROM hyper_estimate LIMIT 2; -SELECT count(*) FROM disttable; - count -------- - 34 -(1 row) - --- REMOVE a column on data nodes to check how errors are handled: -CALL distributed_exec($$ ALTER TABLE disttable DROP COLUMN minmaxes $$); -\set ON_ERROR_STOP 0 -INSERT INTO disttable SELECT * FROM datatable; -ERROR: [db_dist_hypertable_1]: column "minmaxes" of relation "disttable" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE disttable; --- Create a new table access method by reusing heap handler -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_2]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_3]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler - remote_exec -------------- - -(1 row) - --- Create distributed hypertable using non-default access method -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp_c float, temp_f float GENERATED ALWAYS AS (temp_c * 9 / 5 + 32) STORED) USING test_am; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 28 | public | disttable | t -(1 row) - --- Make sure that distributed hypertable created on data nodes is --- using the correct table access method -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_1]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_2]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_3]: -hypertable_amname ------------------ -test_am -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that basic operations are working as expected -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, -10.0), - ('2017-01-01 09:11', 3, -5.0), - ('2017-01-01 08:01', 1, 1.0), - ('2017-01-02 08:01', 2, 5.0), - ('2018-07-02 08:01', 87, 10.0), - ('2018-07-01 06:01', 13, 15.0), - ('2018-07-01 09:11', 90, 20.0), - ('2018-07-01 08:01', 29, 24.0); -SELECT * FROM disttable ORDER BY time; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Sun Jan 01 06:01:00 2017 PST | 1 | -10 | 14 - Sun Jan 01 08:01:00 2017 PST | 1 | 1 | 33.8 - Sun Jan 01 09:11:00 2017 PST | 3 | -5 | 23 - Mon Jan 02 08:01:00 2017 PST | 2 | 5 | 41 - Sun Jul 01 06:01:00 2018 PDT | 13 | 15 | 59 - Sun Jul 01 08:01:00 2018 PDT | 29 | 24 | 75.2 - Sun Jul 01 09:11:00 2018 PDT | 90 | 20 | 68 - Mon Jul 02 08:01:00 2018 PDT | 87 | 10 | 50 -(8 rows) - --- Show that GENERATED columns work for INSERT with RETURNING clause --- (should use DataNodeCopy) -TRUNCATE disttable; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeCopy) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - Remote SQL: COPY public.disttable ("time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision -(13 rows) - -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - --- Same values returned with SELECT: -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - -UPDATE disttable SET temp_c=40.0 WHERE device=1; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 -(1 row) - --- Insert another value -INSERT INTO disttable VALUES ('2017-09-01 06:01', 2, 30.0); -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(2 rows) - --- Delete a value based on the generated column -DELETE FROM disttable WHERE temp_f=104; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(1 row) - --- Test also with DataNodeDispatch -TRUNCATE disttable; -SET timescaledb.enable_distributed_insert_with_copy=false; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable("time", device, temp_c) VALUES ($1, $2, $3), ..., ($2998, $2999, $3000) RETURNING "time", device, temp_c, temp_f - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision -(14 rows) - -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Generated columns with SELECT -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Check distributed hypertable within procedure properly drops remote tables --- --- #3663 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (29,public,test,t) -(1 row) - -CREATE PROCEDURE test_drop() LANGUAGE PLPGSQL AS $$ -BEGIN - DROP TABLE test; -END -$$; -CALL test_drop(); -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (30,public,test,t) -(1 row) - -DROP TABLE test; --- Test that stable functions are calculated on the access node. --- --- As a stable function to test, use the timestamp -> timestamptz conversion --- that is stable because it uses the current timezone. --- We have to be careful about `timestamp < timestamptz` comparison. From postgres --- docs: --- When comparing a timestamp without time zone to a timestamp with time zone, --- the former value is assumed to be given in the time zone specified by the --- TimeZone configuration parameter, and is rotated to UTC for comparison to --- the latter value (which is already in UTC internally). --- We don't want this to happen on data node, so we cast the filter value to --- timestamp, and check that this cast happens on the access node and uses the --- current timezone. -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -CREATE TABLE test_tz (time timestamp, v int); -SELECT create_distributed_hypertable('test_tz','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (31,public,test_tz,t) -(1 row) - -INSERT INTO test_tz VALUES ('2018-01-02 12:00:00', 2), ('2018-01-02 11:00:00', 1), - ('2018-01-02 13:00:00', 3), ('2018-01-02 14:00:00', 4); -SET TIME ZONE 'Etc/GMT'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Normal WHERE clause on baserel -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 14:00:00 2018 | 4 -(2 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- Also test different code paths used with aggregation pushdown. -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 2 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- TODO: test HAVING here and in the later now() tests as well. --- Change the timezone and check that the conversion is applied correctly. -SET TIME ZONE 'Etc/GMT+1'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 11:00:00 2018 -(1 row) - -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 12:00:00 2018 | 2 - Tue Jan 02 14:00:00 2018 | 4 -(3 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(30 rows) - -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 3 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(29 rows) - --- Conversion to timestamptz cannot be evaluated at the access node, because the --- argument is a column reference. -SELECT count(*) FROM test_tz WHERE time::timestamptz > now(); - count -------- - 0 -(1 row) - --- According to our docs, JIT is not recommended for use on access node in --- multi-node environment. Turn it off so that it doesn't ruin EXPLAIN for the --- next query. -SET jit = 0; --- Test that operators are evaluated as well. Comparison of timestamp with --- timestamptz is a stable operator, and comparison of two timestamps is an --- immutable operator. This also test that immutable functions using these --- operators as arguments are evaluated. -EXPLAIN (verbose, costs off) -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT * FROM test_tz, dummy -WHERE time > x - + (x = x)::int -- stable - * (x = '2018-01-02 11:00:00'::timestamp)::int -- immutable - * INTERVAL '1 hour'; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v, (('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- Reference value for the above test. -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT x + (x = x)::int * (x = '2018-01-02 11:00:00'::timestamp)::int * INTERVAL '1 hour' -FROM dummy; - ?column? --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Exercise some more stable timestamp-related functions. -EXPLAIN (COSTS OFF, VERBOSE) -SELECT * FROM test_tz WHERE date_trunc('month', time) > date_in('2021-01-01') - AND time::time > '00:00:00'::time - + (INTERVAL '1 hour') * date_part('hour', INTERVAL '1 hour'); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Filter: (((_dist_hyper_31_97_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_97_chunk."time") > '2021-01-01'::date)) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Filter: (((_dist_hyper_31_95_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_95_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Filter: (((_dist_hyper_31_96_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_96_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Filter: (((_dist_hyper_31_98_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_98_chunk."time") > '2021-01-01'::date)) - -(30 rows) - --- Check that the test function for partly overriding now() works. It's very --- hacky and only has effect when we estimate some costs or evaluate sTABLE --- functions in quals on access node, and has no effect in other cases. --- Consider deleting it altogether. -SELECT test.tsl_override_current_timestamptz('2018-01-02 12:00:00 +00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -SELECT count(*) FROM test_tz WHERE time > now(); - count -------- - 3 -(1 row) - -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -RESET TIME ZONE; -DROP TABLE test_tz; --- Check that now() is evaluated on the access node. Also check that it is evaluated --- anew on every execution of a prepared statement. -CREATE TABLE test_now (time timestamp, v int); -SELECT create_distributed_hypertable('test_now','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (32,public,test_now,t) -(1 row) - -PREPARE test_query as -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; -; -BEGIN; -- to fix the value of now(); -INSERT INTO test_now VALUES - (now(), 1), (now() + INTERVAL '1 hour', 1), - (now() + INTERVAL '2 hour', 2 ), (now() + INTERVAL '3 hour', 3); -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - --- Also test different code paths used with aggregation pushdown. --- We can't run EXPLAIN here, because now() is different every time. But the --- strict equality should be enough to detect if now() is being erroneously --- evaluated on data node, where it will differ from time to time. -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 1 -(1 row) - -COMMIT; --- now() will be different in a new transaction. -BEGIN; -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 0 -(1 row) - -COMMIT; -DROP TABLE test_now; -DEALLOCATE test_query; --- Check enabling distributed compression within a --- procedure/function works --- --- #3705 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (33,public,test,t) -(1 row) - -CREATE PROCEDURE test_set_compression() LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); -END -$$; -CALL test_set_compression(); -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_33_103_chunk -(1 row) - -DROP TABLE test; -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (34,public,test,t) -(1 row) - -CREATE FUNCTION test_set_compression_func() RETURNS BOOL LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); - RETURN TRUE; -END -$$; -SELECT test_set_compression_func(); - test_set_compression_func ---------------------------- - t -(1 row) - -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_34_104_chunk -(1 row) - -DROP TABLE test; --- Fix ALTER SET/DROP NULL constraint on distributed hypertable --- --- #3860 --- -CREATE TABLE test (time timestamp NOT NULL, my_column int NOT NULL); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (35,public,test,t) -(1 row) - -\set ON_ERROR_STOP 0 -INSERT INTO test VALUES (now(), NULL); -ERROR: [db_dist_hypertable_3]: null value in column "my_column" of relation "_dist_hyper_35_105_chunk" violates not-null constraint -\set ON_ERROR_STOP 1 -ALTER TABLE test ALTER COLUMN my_column DROP NOT NULL; -INSERT INTO test VALUES (now(), NULL); -\set ON_ERROR_STOP 0 -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -ERROR: [db_dist_hypertable_3]: column "my_column" of relation "_dist_hyper_35_106_chunk" contains null values -\set ON_ERROR_STOP 1 -DELETE FROM test; -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -DROP TABLE test; --- Test insert into distributed hypertable with pruned chunks -CREATE TABLE pruned_chunks_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_1', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_1 -(1 row) - -INSERT INTO pruned_chunks_1 VALUES ('2020-12-09',1,32.2); -CREATE TABLE pruned_chunks_2(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); --- Convert the table to a distributed hypertable -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_2', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_2 -(1 row) - -insert into pruned_chunks_2 select * from pruned_chunks_1; -insert into pruned_chunks_2 select * from pruned_chunks_1 WHERE time > '2022-01-01'; --- TEST freeze_chunk api. does not work for distributed chunks -SELECT chunk_schema || '.' || chunk_name as "CHNAME" -FROM timescaledb_information.chunks -WHERE hypertable_name = 'pruned_chunks_1' -ORDER BY chunk_name LIMIT 1 -\gset -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( :'CHNAME'); -ERROR: operation not supported on distributed chunk or foreign table "_dist_hyper_36_107_chunk" -\set ON_ERROR_STOP 1 ---TEST freeze_chunk api for regular hypertables. Works only for >= PG14 -CREATE TABLE freeze_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_hypertable('freeze_1', 'time'); - table_name ------------- - freeze_1 -(1 row) - -INSERT INTO freeze_1 VALUES ('2020-12-09',1,32.2); -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( ch) FROM ( select show_chunks('freeze_1') ch ) q; - freeze_chunk --------------- - t -(1 row) - -\set ON_ERROR_STOP 1 -DROP TABLE pruned_chunks_1; -DROP TABLE pruned_chunks_2; --- Cleanup -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_hypertable-15.out b/tsl/test/expected/dist_hypertable-15.out deleted file mode 100644 index 87096ac7df6..00000000000 --- a/tsl/test/expected/dist_hypertable-15.out +++ /dev/null @@ -1,6315 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_1 | db_dist_hypertable_1 | t | t | t - db_dist_hypertable_2 | db_dist_hypertable_2 | t | t | t - db_dist_hypertable_3 | db_dist_hypertable_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; --- Import testsupport.sql file to data nodes -\unset ECHO -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; ---Ensure INSERTs use DataNodeDispatch. DataNodeCopy is tested later -SET timescaledb.enable_distributed_insert_with_copy=false; --- Verify lack of tables -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -\set ON_ERROR_STOP 0 --- Test that one cannot directly create TimescaleDB foreign tables -CREATE FOREIGN TABLE foreign_table (time timestamptz, device int, temp float) SERVER :DATA_NODE_1; -ERROR: operation not supported -\set ON_ERROR_STOP 1 --- Create distributed hypertables. Add a trigger and primary key --- constraint to test how those work -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), color int, temp float, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 1); -WARNING: distributed hypertable is deprecated -WARNING: insufficient number of partitions for dimension "device" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | disttable | t -(1 row) - --- Increase the number of partitions. Expect warning since still too --- low. Dimension partitions should be updated to reflect new --- partitioning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} -(1 row) - -SELECT * FROM set_number_partitions('disttable', 2); -WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - --- Set number of partitions equal to the number of servers should not --- raise a warning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 1073741823 | {db_dist_hypertable_2} -(2 rows) - -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show the number of slices -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'disttable'; - table_name | column_name | num_slices -------------+-------------+------------ - disttable | device | 3 - disttable | time | -(2 rows) - --- This table tests both 1-dimensional tables and under-replication --- (replication_factor > num_data_nodes). -CREATE TABLE underreplicated(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 --- can't create an under-replicated hypertable -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -ERROR: replication factor too large for hypertable "underreplicated" -\set ON_ERROR_STOP 1 -RESET ROLE; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node(:'DATA_NODE_4', host => 'localhost', database => :'DATA_NODE_4'); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_hypertable_4 | db_dist_hypertable_4 | t | t | t -(1 row) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_4 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 2 | public | underreplicated | t -(1 row) - --- test that attaching a data node to an existing hypertable with --- repartition=>false does not change the number of partitions when --- number of partitions is greater than number of data nodes. -SELECT * FROM set_number_partitions('disttable', 8, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - -SELECT attach_data_node(:'DATA_NODE_4', 'disttable', repartition => false); -WARNING: attaching data node is deprecated - attach_data_node ----------------------------- - (1,2,db_dist_hypertable_4) -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_4} - disttable | 2 | 1073741820 | {db_dist_hypertable_1} - disttable | 2 | 1342177275 | {db_dist_hypertable_2} - disttable | 2 | 1610612730 | {db_dist_hypertable_3} - disttable | 2 | 1879048185 | {db_dist_hypertable_4} -(8 rows) - ---create new session to clear out connections -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_4', force => true, drop_database => true, repartition => false); -WARNING: deleting data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "underreplicated" - delete_data_node ------------------- - t -(1 row) - -SET ROLE :ROLE_1; --- Deleting a data node should also not change the number of --- partitions with repartition=>false -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 268435455 | {db_dist_hypertable_2} - disttable | 2 | 536870910 | {db_dist_hypertable_3} - disttable | 2 | 805306365 | {db_dist_hypertable_1} - disttable | 2 | 1073741820 | {db_dist_hypertable_2} - disttable | 2 | 1342177275 | {db_dist_hypertable_3} - disttable | 2 | 1610612730 | {db_dist_hypertable_1} - disttable | 2 | 1879048185 | {db_dist_hypertable_2} -(8 rows) - --- reset to 3 partitions -SELECT * FROM set_number_partitions('disttable', 3, 'device'); - set_number_partitions ------------------------ - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; --- Create the trigger function on the data nodes: -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; -$$); -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 1,2,3; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+----------------------+-------------- - 1 | 1 | db_dist_hypertable_1 | f - 1 | 1 | db_dist_hypertable_2 | f - 1 | 1 | db_dist_hypertable_3 | f - 2 | 2 | db_dist_hypertable_1 | f - 2 | 2 | db_dist_hypertable_2 | f - 2 | 2 | db_dist_hypertable_3 | f -(6 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+----------- -(0 rows) - --- The constraints, indexes, and triggers on the hypertable -SELECT * FROM test.show_constraints('disttable'); - Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated -------------------------+------+---------------+----------------+--------------+------------+----------+----------- - disttable_device_check | c | {device} | - | (device > 0) | f | f | t - disttable_pkey | p | {time,device} | disttable_pkey | | f | f | t -(2 rows) - -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_idx | {time} | | f | f | f | -(3 rows) - -SELECT * FROM test.show_triggers('disttable'); - Trigger | Type | Function -------------------------+------+--------------------------------------- - _0_test_trigger_insert | 7 | test_trigger - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(2 rows) - --- Drop a column. This will make the attribute numbers of the --- hypertable's root relation differ from newly created chunks. It is --- a way to test that we properly handle attributed conversion between --- the root table and chunks -ALTER TABLE disttable DROP COLUMN color; --- EXPLAIN some inserts to see what plans and explain output for --- remote inserts look like -EXPLAIN (COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeCopy) - -> Custom Scan (ChunkDispatch) - -> Result -(6 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable - -> Custom Scan (DataNodeCopy) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - Remote SQL: COPY public.disttable ("time", device, temp) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision - -> Result - Output: 'Sun Jan 01 06:01:00 2017 PST'::timestamp with time zone, 1, NULL::integer, '1.1'::double precision -(11 rows) - --- Create some chunks through insertion -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 09:21', 3, 2.2), - ('2017-01-01 08:11', 3, 2.3), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2017-01-02 09:01', 2, 1.4), - ('2017-01-02 08:21', 2, 1.5), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-02 09:01', 87, 1.4), - ('2018-07-02 09:21', 87, 1.8), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 06:21', 13, 1.5), - ('2018-07-01 07:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5), - ('2018-07-01 09:21', 90, 2.8), - ('2018-07-01 08:21', 29, 1.2); --- EXPLAIN some updates/deletes to see what plans and explain output for --- remote operations look like -EXPLAIN (VERBOSE, COSTS FALSE) -UPDATE disttable SET temp = 3.7 WHERE device = 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ - Update on public.disttable - Update on public.disttable disttable_1 - Foreign Update on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_1_chunk SET temp = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_1_4_chunk SET temp = $2 WHERE ctid = $1 - -> Result - Output: '3.7'::double precision, disttable.tableoid, disttable.ctid, (NULL::record) - -> Append - -> Seq Scan on public.disttable disttable_1 - Output: disttable_1.tableoid, disttable_1.ctid, NULL::record - Filter: (disttable_1.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Output: disttable_2.tableoid, disttable_2.ctid, disttable_2.* - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, temp, ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Output: disttable_3.tableoid, disttable_3.ctid, disttable_3.* - Data node: db_dist_hypertable_1 - Remote SQL: SELECT "time", device, temp, ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) -(20 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -DELETE FROM disttable WHERE device = 1; - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Delete on public.disttable - Delete on public.disttable disttable_1 - Foreign Delete on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ctid = $1 - Foreign Delete on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Remote SQL: DELETE FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ctid = $1 - -> Append - -> Seq Scan on public.disttable disttable_1 - Output: disttable_1.tableoid, disttable_1.ctid - Filter: (disttable_1.device = 1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk disttable_2 - Output: disttable_2.tableoid, disttable_2.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_1_chunk WHERE ((device = 1)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk disttable_3 - Output: disttable_3.tableoid, disttable_3.ctid - Data node: db_dist_hypertable_1 - Remote SQL: SELECT ctid FROM _timescaledb_internal._dist_hyper_1_4_chunk WHERE ((device = 1)) -(18 rows) - --- Test distributed ANALYZE. --- --- First show no statistics --- reltuples is initially -1 before any VACUUM/ANALYZE has been run on PG14 -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 0 | 0 - _dist_hyper_1_2_chunk | f | 0 | 0 - _dist_hyper_1_3_chunk | f | 0 | 0 - _dist_hyper_1_4_chunk | f | 0 | 0 - _dist_hyper_1_5_chunk | f | 0 | 0 - _dist_hyper_1_6_chunk | f | 0 | 0 -(6 rows) - -ANALYZE disttable; --- Show updated statistics -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - relname | relkind | reltuples | relpages ------------+---------+-----------+---------- - disttable | r | 0 | 0 -(1 row) - -SELECT relname, relkind, reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - relname | relkind | reltuples | relpages ------------------------+---------+-----------+---------- - _dist_hyper_1_1_chunk | f | 2 | 1 - _dist_hyper_1_2_chunk | f | 3 | 1 - _dist_hyper_1_3_chunk | f | 3 | 1 - _dist_hyper_1_4_chunk | f | 3 | 1 - _dist_hyper_1_5_chunk | f | 3 | 1 - _dist_hyper_1_6_chunk | f | 4 | 1 -(6 rows) - --- Test distributed VACUUM. --- -VACUUM (FULL, ANALYZE) disttable; -VACUUM FULL disttable; -VACUUM disttable; -\set ON_ERROR_STOP 0 --- VACUUM VERBOSE is not supported at the moment -VACUUM VERBOSE disttable; -ERROR: operation not supported on distributed hypertable -\set ON_ERROR_STOP 1 --- Test prepared statement -PREPARE dist_insert (timestamptz, int, float) AS -INSERT INTO disttable VALUES ($1, $2, $3); -EXECUTE dist_insert ('2017-01-01 06:05', 1, 1.4); --- Show chunks created -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-----------------------+---------+--------------------------------------------------------------------------------------------- - 1 | 1 | _timescaledb_internal | _dist_hyper_1_1_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2 | 1 | _timescaledb_internal | _dist_hyper_1_2_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 3 | 1 | _timescaledb_internal | _dist_hyper_1_3_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 4 | 1 | _timescaledb_internal | _dist_hyper_1_4_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 5 | 1 | _timescaledb_internal | _dist_hyper_1_5_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 6 | 1 | _timescaledb_internal | _dist_hyper_1_6_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show that there are assigned node_chunk_id:s in chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - -SELECT * FROM hypertable_partitions; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - disttable | 2 | -9223372036854775808 | {db_dist_hypertable_1} - disttable | 2 | 715827882 | {db_dist_hypertable_2} - disttable | 2 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - --- Show that chunks are created on data nodes and that each data node --- has their own unique slice in the space (device) dimension. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6 -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4 -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8 -(6 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3 -Mon Jan 02 09:01:00 2017 PST| 2| 1.4 -Mon Jan 02 08:21:00 2017 PST| 2| 1.5 -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4 -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5 -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4 -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1 -Sun Jan 01 09:21:00 2017 PST| 3| 2.2 -Sun Jan 01 08:11:00 2017 PST| 3| 2.3 -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7 -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5 -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8 -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2 -(7 rows) - - - remote_exec -------------- - -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - node_name ----------------------- - db_dist_hypertable_1 - db_dist_hypertable_2 - db_dist_hypertable_3 -(3 rows) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+---------------------- - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_1 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_2 - 81920 | 122880 | 0 | 204800 | db_dist_hypertable_3 - 0 | 24576 | 0 | 24576 | -(4 rows) - --- Show what some queries would look like on the frontend -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT * FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: disttable."time", disttable.device, disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time", disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time", disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time", disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(18 rows) - -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -ORDER BY 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - GroupAggregate - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, avg(disttable.temp) - Group Key: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 3 hours'::interval, disttable."time")), disttable.device, disttable.temp - -> Merge Append - Sort Key: (time_bucket('@ 3 hours'::interval, disttable_1."time")), disttable_1.device - -> Result - Output: time_bucket('@ 3 hours'::interval, disttable_1."time"), disttable_1.device, disttable_1.temp - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time", disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 3 hours'::interval, disttable_2."time"), disttable_2.device, disttable_2.temp - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time", disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 3 hours'::interval, disttable_3."time"), disttable_3.device, disttable_3.temp - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time", disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT "time", device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY public.time_bucket('03:00:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(28 rows) - --- Execute some queries on the frontend and return the results -SELECT * FROM disttable; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 -(19 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -GROUP BY 1, 2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 1 | 1.2 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(8 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+------------------ - Sun Jan 01 04:00:00 2017 PST | 1 | 1.25 - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.4 - Sun Jul 01 05:00:00 2018 PDT | 13 | 1.43333333333333 - Sun Jul 01 08:00:00 2018 PDT | 29 | 1.35 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 - Mon Jul 02 08:00:00 2018 PDT | 87 | 1.6 -(7 rows) - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -WHERE temp > 2 -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 3 | 2.2 - Sun Jul 01 08:00:00 2018 PDT | 90 | 2.75 -(2 rows) - --- Test AsyncAppend when using min/max aggregates -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(24 rows) - -SELECT max(temp) -FROM disttable; - max ------ - 2.8 -(1 row) - --- Test turning off async append -SET timescaledb.enable_async_append = OFF; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable_1.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 -(22 rows) - -SET timescaledb.enable_async_append = ON; -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT min(temp), max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate - Output: min(disttable.temp), max(disttable.temp) - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Append - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) -(20 rows) - -SELECT min(temp), max(temp) -FROM disttable; - min | max ------+----- - 1.1 | 2.8 -(1 row) - --- Test AsyncAppend when using window functions -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: disttable.device, disttable.temp, (avg(disttable.temp) OVER (?)) - Sort Key: disttable.device, disttable.temp - -> WindowAgg - Output: disttable.device, disttable.temp, avg(disttable.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: disttable.device, disttable.temp - -> Merge Append - Sort Key: disttable_1.device - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.device, disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.device, disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.device, disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT device, temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) ORDER BY device ASC NULLS LAST -(24 rows) - -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - device | temp | avg ---------+------+------------------ - 1 | 1.1 | 1.23333333333333 - 1 | 1.2 | 1.23333333333333 - 1 | 1.4 | 1.23333333333333 - 2 | 1.3 | 1.4 - 2 | 1.4 | 1.4 - 2 | 1.5 | 1.4 - 3 | 2.1 | 2.2 - 3 | 2.2 | 2.2 - 3 | 2.3 | 2.2 - 13 | 1.4 | 1.43333333333333 - 13 | 1.4 | 1.43333333333333 - 13 | 1.5 | 1.43333333333333 - 29 | 1.2 | 1.35 - 29 | 1.5 | 1.35 - 87 | 1.4 | 1.6 - 87 | 1.6 | 1.6 - 87 | 1.8 | 1.6 - 90 | 2.7 | 2.75 - 90 | 2.8 | 2.75 -(19 rows) - --- Test remote explain --- Make sure that chunks_in function only expects one-dimensional integer arrays -\set ON_ERROR_STOP 0 -SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[[2], [1]]) -ORDER BY "time" DESC NULLS FIRST LIMIT 1; -ERROR: invalid number of array dimensions for chunks_in -\set ON_ERROR_STOP 1 -SET timescaledb.enable_remote_explain = ON; --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when using max(time). -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(time) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable."time" - -> Custom Scan (AsyncAppend) - Output: disttable."time" - -> Merge Append - Sort Key: disttable_1."time" DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1."time" - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_4_chunk, _dist_hyper_1_1_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_4_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk."time" - Index Cond: (_dist_hyper_1_4_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_1_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk."time" - Index Cond: (_dist_hyper_1_1_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2."time" - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_5_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk."time" - Index Cond: (_dist_hyper_1_5_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_3_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk."time" - Index Cond: (_dist_hyper_1_3_chunk."time" IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3."time" - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_6_chunk, _dist_hyper_1_2_chunk - Remote SQL: SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[2, 1]) AND (("time" IS NOT NULL)) ORDER BY "time" DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: disttable."time" - -> Custom Scan (ChunkAppend) on public.disttable - Output: disttable."time" - Order: disttable."time" DESC - Startup Exclusion: false - Runtime Exclusion: false - -> Index Only Scan using _dist_hyper_1_6_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk."time" - Index Cond: (_dist_hyper_1_6_chunk."time" IS NOT NULL) - -> Index Only Scan using _dist_hyper_1_2_chunk_disttable_time_idx on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk."time" - Index Cond: (_dist_hyper_1_2_chunk."time" IS NOT NULL) - -(69 rows) - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result - Output: $0 - InitPlan 1 (returns $0) - -> Limit - Output: disttable.temp - -> Custom Scan (AsyncAppend) - Output: disttable.temp - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_1_chunk.temp - -> Sort - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_3_chunk.temp - -> Sort - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit - Output: _dist_hyper_1_2_chunk.temp - -> Sort - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - -> Append - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(66 rows) - --- Don't remote explain if there is no VERBOSE flag -EXPLAIN (COSTS FALSE) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------- - Result - InitPlan 1 (returns $0) - -> Limit - -> Custom Scan (AsyncAppend) - -> Merge Append - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on disttable disttable_1 - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 -(9 rows) - --- Test additional EXPLAIN flags -EXPLAIN (ANALYZE, VERBOSE, COSTS FALSE, BUFFERS OFF, TIMING OFF, SUMMARY OFF) -SELECT max(temp) -FROM disttable; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=1 loops=1) - Output: $0 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable.temp - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable.temp - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_1.temp DESC - -> Custom Scan (DataNodeScan) on public.disttable disttable_1 (actual rows=1 loops=1) - Output: disttable_1.temp - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Sort Key: _dist_hyper_1_1_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_1_chunk.temp - Filter: (_dist_hyper_1_1_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_4_chunk.temp - Filter: (_dist_hyper_1_4_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_2 (actual rows=1 loops=1) - Output: disttable_2.temp - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_5_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Sort Key: _dist_hyper_1_3_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=6 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_3_chunk.temp - Filter: (_dist_hyper_1_3_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_5_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_5_chunk.temp - Filter: (_dist_hyper_1_5_chunk.temp IS NOT NULL) - - -> Custom Scan (DataNodeScan) on public.disttable disttable_3 (actual rows=1 loops=1) - Output: disttable_3.temp - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_6_chunk - Remote SQL: SELECT temp FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[1, 2]) AND ((temp IS NOT NULL)) ORDER BY temp DESC NULLS FIRST LIMIT 1 - Remote EXPLAIN: - Limit (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - -> Sort (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Sort Key: _dist_hyper_1_2_chunk.temp DESC - Sort Method: top-N heapsort - -> Append (actual rows=7 loops=1) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=3 loops=1) - Output: _dist_hyper_1_2_chunk.temp - Filter: (_dist_hyper_1_2_chunk.temp IS NOT NULL) - -> Seq Scan on _timescaledb_internal._dist_hyper_1_6_chunk (actual rows=4 loops=1) - Output: _dist_hyper_1_6_chunk.temp - Filter: (_dist_hyper_1_6_chunk.temp IS NOT NULL) - -(72 rows) - --- The constraints, indexes, and triggers on foreign chunks. Only --- check constraints should recurse to foreign chunks (although they --- aren't enforced on a foreign table) -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) -(18 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that the chunks are assigned data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 1 | 1 | db_dist_hypertable_1 - 2 | 1 | db_dist_hypertable_3 - 3 | 1 | db_dist_hypertable_2 - 4 | 2 | db_dist_hypertable_1 - 5 | 2 | db_dist_hypertable_2 - 6 | 2 | db_dist_hypertable_3 -(6 rows) - --- Adding a new trigger should not recurse to foreign chunks -CREATE TRIGGER _1_test_trigger_insert - AFTER INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_triggers --------------+--------------- -(0 rows) - --- Check that we can create indexes on distributed hypertables and --- that they don't recurse to foreign chunks -CREATE INDEX ON disttable (time, device); -SELECT * FROM test.show_indexes('disttable'); - Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace ----------------------------+---------------+------+--------+---------+-----------+------------ - disttable_device_time_idx | {device,time} | | f | f | f | - disttable_pkey | {time,device} | | t | t | f | - disttable_time_device_idx | {time,device} | | f | f | f | - disttable_time_idx | {time} | | f | f | f | -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_indexes --------------+-------------- -(0 rows) - --- No index mappings should exist either -SELECT * FROM _timescaledb_catalog.chunk_index; - chunk_id | index_name | hypertable_id | hypertable_index_name -----------+------------+---------------+----------------------- -(0 rows) - --- Check that creating columns work -ALTER TABLE disttable ADD COLUMN "Color" int; -SELECT * FROM test.show_columns('disttable'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | t - temp | double precision | f - Color | integer | f -(4 rows) - -SELECT st."Child" as chunk_relid, test.show_columns((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_columns ----------------------------------------------+------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_1_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_1_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_2_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_2_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_2_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_3_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_3_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_3_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_4_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_4_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_4_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_5_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_5_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_5_chunk | (Color,integer,f) - _timescaledb_internal._dist_hyper_1_6_chunk | (time,"timestamp with time zone",t) - _timescaledb_internal._dist_hyper_1_6_chunk | (device,integer,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (temp,"double precision",f) - _timescaledb_internal._dist_hyper_1_6_chunk | (Color,integer,f) -(24 rows) - --- Adding a new unique constraint should not recurse to foreign --- chunks, but a check constraint should -ALTER TABLE disttable ADD CONSTRAINT disttable_color_unique UNIQUE (time, device, "Color"); -ALTER TABLE disttable ADD CONSTRAINT disttable_temp_non_negative CHECK (temp > 0.0); -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - chunk_relid | show_constraints ----------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_1_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_2_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_1,c,{time},-,"((""time"" >= 'Wed Dec 28 16:00:00 2016 PST'::timestamp with time zone) AND (""time"" < 'Wed Jan 04 16:00:00 2017 PST'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_3_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_2,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) < 715827882)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_4_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_4,c,{device},-,"((_timescaledb_functions.get_partition_hash(device) >= 715827882) AND (_timescaledb_functions.get_partition_hash(device) < 1431655764))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_5_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_3,c,{device},-,"(_timescaledb_functions.get_partition_hash(device) >= 1431655764)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (constraint_5,c,{time},-,"((""time"" >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (""time"" < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone))",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_device_check,c,{device},-,"(device > 0)",f,f,t) - _timescaledb_internal._dist_hyper_1_6_chunk | (disttable_temp_non_negative,c,{temp},-,"(temp > (0.0)::double precision)",f,f,t) -(24 rows) - -SELECT cc.* -FROM (SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('disttable')) c, - _timescaledb_catalog.chunk_constraint cc -WHERE c.chunk_id = cc.chunk_id; - chunk_id | dimension_slice_id | constraint_name | hypertable_constraint_name -----------+--------------------+-----------------+---------------------------- - 1 | 2 | constraint_2 | - 1 | 1 | constraint_1 | - 2 | 3 | constraint_3 | - 2 | 1 | constraint_1 | - 3 | 4 | constraint_4 | - 3 | 1 | constraint_1 | - 4 | 2 | constraint_2 | - 4 | 5 | constraint_5 | - 5 | 4 | constraint_4 | - 5 | 5 | constraint_5 | - 6 | 3 | constraint_3 | - 6 | 5 | constraint_5 | -(12 rows) - --- Show contents after re-adding column -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | -(19 rows) - --- Test INSERTS with RETURNING. Since we previously dropped a column --- on the hypertable, this also tests that we handle conversion of the --- attribute numbers in the RETURNING clause, since they now differ --- between the hypertable root relation and the chunk currently --- RETURNING from. -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 4, 1, 9.8) -RETURNING time, "Color", temp; - time | Color | temp -------------------------------+-------+------ - Sat Sep 02 06:09:00 2017 PDT | 1 | 9.8 -(1 row) - -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-03 06:18', 9, 3, 8.7) -RETURNING 1; - ?column? ----------- - 1 -(1 row) - --- On conflict -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 6, 2, 10.5) -ON CONFLICT DO NOTHING; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_1_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 2| 1|_timescaledb_internal|_dist_hyper_1_4_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 3| 1|_timescaledb_internal|_dist_hyper_1_9_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+--------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_3_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 2| 1|_timescaledb_internal|_dist_hyper_1_5_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 3| 1|_timescaledb_internal|_dist_hyper_1_7_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [715827882, 1431655764]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+---------------------+-------+------------------------------------------------------------------------------------------- - 1| 1|_timescaledb_internal|_dist_hyper_1_2_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 2| 1|_timescaledb_internal|_dist_hyper_1_6_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} - 3| 1|_timescaledb_internal|_dist_hyper_1_8_chunk|r |{"time": [1504137600000000, 1504742400000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - - - remote_exec -------------- - -(1 row) - --- Show new row and that conflicting row is not inserted -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -(7 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -Sat Sep 02 06:09:00 2017 PDT| 4| 9.8| 1 -(7 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 09:11:00 2017 PST| 3| 2.1| -Sun Jan 01 09:21:00 2017 PST| 3| 2.2| -Sun Jan 01 08:11:00 2017 PST| 3| 2.3| -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 3 -(8 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 --- ON CONFLICT DO NOTHING only works when index inference is omitted -\set VERBOSITY default -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device) DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_pkey" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device,"Color") DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT ON CONSTRAINT disttable_color_unique DO NOTHING; -ERROR: could not find arbiter index for hypertable index "disttable_color_unique" on chunk "_dist_hyper_1_9_chunk" -HINT: Omit the index inference specification for the distributed hypertable in the ON CONFLICT clause. -\set VERBOSITY terse -SELECT * FROM disttable ORDER BY disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 3 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | -(22 rows) - --- ON CONFLICT only works with DO NOTHING for now -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-09 08:13', 7, 3, 27.5) -ON CONFLICT (time) DO UPDATE SET temp = 3.2; -ERROR: ON CONFLICT DO UPDATE not supported on distributed hypertables --- Test that an INSERT that would create a chunk does not work on a --- data node -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) - -ERROR: [db_dist_hypertable_1]: distributed hypertable member cannot create chunk on its own -\set ON_ERROR_STOP 1 --- However, INSERTs on a data node that does not create a chunk works. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE disttable SET "Color" = 4 WHERE "Color" = 3; -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 9 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(23 rows) - -WITH devices AS ( - SELECT DISTINCT device FROM disttable ORDER BY device -) -UPDATE disttable SET "Color" = 2 WHERE device = (SELECT device FROM devices LIMIT 1); -\set ON_ERROR_STOP 0 --- Updates referencing non-existing column -UPDATE disttable SET device = 4 WHERE no_such_column = 2; -ERROR: column "no_such_column" does not exist at character 39 -UPDATE disttable SET no_such_column = 4 WHERE device = 2; -ERROR: column "no_such_column" of relation "disttable" does not exist at character 22 --- Update to system column -UPDATE disttable SET tableoid = 4 WHERE device = 2; -ERROR: cannot assign to system column "tableoid" at character 22 -\set ON_ERROR_STOP 1 --- Test deletes (no rows deleted) -DELETE FROM disttable WHERE device = 3 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 | - Sun Jan 01 09:21:00 2017 PST | 3 | 2.2 | - Sun Jan 01 08:11:00 2017 PST | 3 | 2.3 | -(3 rows) - -DELETE FROM disttable WHERE time IS NULL; --- Test deletes (rows deleted) -DELETE FROM disttable WHERE device = 4 -RETURNING *; - time | device | temp | Color -------------------------------+--------+------+------- - Sat Sep 02 06:09:00 2017 PDT | 4 | 9.8 | 1 -(1 row) - --- Query to show that rows are deleted -SELECT * FROM disttable; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Sun Jan 01 06:05:00 2017 PST | 1 | 1.4 | 2 - Mon Jul 02 08:01:00 2018 PDT | 87 | 1.6 | - Mon Jul 02 09:01:00 2018 PDT | 87 | 1.4 | - Mon Jul 02 09:21:00 2018 PDT | 87 | 1.8 | - Sat Sep 02 06:09:00 2017 PDT | 6 | 10.5 | 2 - Sun Sep 03 06:09:00 2017 PDT | 1 | 2 | 2 - Mon Jan 02 08:01:00 2017 PST | 2 | 1.3 | - Mon Jan 02 09:01:00 2017 PST | 2 | 1.4 | - Mon Jan 02 08:21:00 2017 PST | 2 | 1.5 | - Sun Jul 01 06:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 06:21:00 2018 PDT | 13 | 1.5 | - Sun Jul 01 07:01:00 2018 PDT | 13 | 1.4 | - Sun Jul 01 09:11:00 2018 PDT | 90 | 2.7 | - Sun Jul 01 08:01:00 2018 PDT | 29 | 1.5 | - Sun Jul 01 09:21:00 2018 PDT | 90 | 2.8 | - Sun Jul 01 08:21:00 2018 PDT | 29 | 1.2 | - Sun Sep 03 06:18:00 2017 PDT | 9 | 8.7 | 4 -(19 rows) - --- Ensure rows are deleted on the data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1| 2 -Sun Jan 01 08:01:00 2017 PST| 1| 1.2| 2 -Sun Jan 01 06:05:00 2017 PST| 1| 1.4| 2 -Mon Jul 02 08:01:00 2018 PDT| 87| 1.6| -Mon Jul 02 09:01:00 2018 PDT| 87| 1.4| -Mon Jul 02 09:21:00 2018 PDT| 87| 1.8| -Sat Sep 02 06:09:00 2017 PDT| 6|10.5| 2 -Sun Sep 03 06:09:00 2017 PDT| 1| 2| 2 -(8 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time |device|temp|Color -----------------------------+------+----+----- -Mon Jan 02 08:01:00 2017 PST| 2| 1.3| -Mon Jan 02 09:01:00 2017 PST| 2| 1.4| -Mon Jan 02 08:21:00 2017 PST| 2| 1.5| -Sun Jul 01 06:01:00 2018 PDT| 13| 1.4| -Sun Jul 01 06:21:00 2018 PDT| 13| 1.5| -Sun Jul 01 07:01:00 2018 PDT| 13| 1.4| -(6 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time |device|temp|Color -----------------------------+------+----+----- -Sun Jul 01 09:11:00 2018 PDT| 90| 2.7| -Sun Jul 01 08:01:00 2018 PDT| 29| 1.5| -Sun Jul 01 09:21:00 2018 PDT| 90| 2.8| -Sun Jul 01 08:21:00 2018 PDT| 29| 1.2| -Sun Sep 03 06:18:00 2017 PDT| 9| 8.7| 4 -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Test TRUNCATE -TRUNCATE disttable; --- No data should remain -SELECT * FROM disttable; - time | device | temp | Color -------+--------+------+------- -(0 rows) - --- Metadata and tables cleaned up -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-------------+------------+---------------------+---------+--------+----------- -(0 rows) - -SELECT * FROM show_chunks('disttable'); - show_chunks -------------- -(0 rows) - --- Also cleaned up remotely -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM show_chunks('disttable'); -SELECT * FROM disttable; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_1]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_1]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_2]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_2]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|schema_name|table_name|compressed_chunk_id|dropped|status|osm_chunk ---+-------------+-----------+----------+-------------------+-------+------+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM show_chunks('disttable') -NOTICE: [db_dist_hypertable_3]: -show_chunks ------------ -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM disttable -NOTICE: [db_dist_hypertable_3]: -time|device|temp|Color -----+------+----+----- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- The hypertable view also shows no chunks and no data -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 0 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test underreplicated chunk warning -INSERT INTO underreplicated VALUES ('2017-01-01 06:01', 1, 1.1), - ('2017-01-02 07:01', 2, 3.5); -WARNING: insufficient number of data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+------------------------+---------+------------------------------------------------ - 10 | 2 | _timescaledb_internal | _dist_hyper_2_10_chunk | f | {"time": [1482969600000000, 1483574400000000]} -(1 row) - --- Show chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - chunk_id | node_chunk_id | node_name -----------+---------------+---------------------- - 10 | 4 | db_dist_hypertable_1 - 10 | 4 | db_dist_hypertable_2 - 10 | 4 | db_dist_hypertable_3 -(3 rows) - --- Show that chunks are created on remote data nodes and that all --- data nodes/chunks have the same data due to replication -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+----------------------+-------+---------------------------------------------- - 4| 2|_timescaledb_internal|_dist_hyper_2_10_chunk|r |{"time": [1482969600000000, 1483574400000000]} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 3.5 -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Test updates -UPDATE underreplicated SET temp = 2.0 WHERE device = 2 -RETURNING time, temp, device; - time | temp | device -------------------------------+------+-------- - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - -SELECT * FROM underreplicated; - time | device | temp -------------------------------+--------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(2 rows) - --- Show that all replica chunks are updated -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -Mon Jan 02 07:01:00 2017 PST| 2| 2 -(2 rows) - - - remote_exec -------------- - -(1 row) - -DELETE FROM underreplicated WHERE device = 2 -RETURNING *; - time | device | temp -------------------------------+--------+------ - Mon Jan 02 07:01:00 2017 PST | 2 | 2 -(1 row) - --- Ensure deletes across all data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_1]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_2]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test hypertable creation fails on distributed error -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float); -SELECT * FROM underreplicated; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_3]: -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float) -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM underreplicated -NOTICE: [db_dist_hypertable_3]: -time |device|temp -----------------------------+------+---- -Sun Jan 01 06:01:00 2017 PST| 1| 1.1 -(1 row) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_hypertable('remotetable', 'time', replication_factor => 1); -ERROR: [db_dist_hypertable_3]: relation "remotetable" already exists --- Test distributed_hypertable creation fails with replication factor 0 -CREATE TABLE remotetable2(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_distributed_hypertable('remotetable2', 'time', replication_factor => 0); -WARNING: distributed hypertable is deprecated -ERROR: invalid replication factor -\set ON_ERROR_STOP 1 -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+------------------------------------------------------------------+------------- - public | disttable | test_role_1 | 2 | 0 | f | t | 1 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | - public | underreplicated | test_role_1 | 1 | 1 | f | t | 4 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} | -(2 rows) - --- Test distributed hypertable creation with many parameters -\c :TEST_DBNAME :ROLE_SUPERUSER ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE SCHEMA "T3sTSch"; -CREATE SCHEMA "Table\\Schema"; -CREATE SCHEMA "single'schema"; -GRANT ALL ON SCHEMA "T3sTSch" TO :ROLE_1; -GRANT ALL ON SCHEMA "Table\\Schema" TO :ROLE_1; -GRANT ALL ON SCHEMA "single'schema" TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE "Table\\Schema"."Param_Table"("time Col %#^#@$#" timestamptz, __region text, reading float); -SELECT * FROM create_distributed_hypertable('"Table\\Schema"."Param_Table"', 'time Col %#^#@$#', partitioning_column => '__region', -associated_schema_name => 'T3sTSch', associated_table_prefix => 'test*pre_', chunk_time_interval => interval '1 week', -create_default_indexes => FALSE, if_not_exists => TRUE, replication_factor => 2, -data_nodes => ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time Col %#^#@$#" - hypertable_id | schema_name | table_name | created ----------------+---------------+-------------+--------- - 4 | Table\\Schema | Param_Table | t -(1 row) - --- Test detach and attach data node -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, drop_remote_data => true); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 1 - detach_data_node ------------------- - 1 -(1 row) - --- Test attach_data_node. First show dimensions and currently attached --- servers. The number of slices in the space dimension should equal --- the number of servers since we didn't explicitly specify --- number_partitions -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 1 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_3 -(1 row) - -SELECT * FROM attach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"'); -WARNING: attaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" was increased to 2 - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 3 | db_dist_hypertable_1 -(1 row) - --- Show updated metadata after attach -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - table_name | node_name --------------+---------------------- - Param_Table | db_dist_hypertable_1 - Param_Table | db_dist_hypertable_3 -(2 rows) - --- Attach another data node but do not auto-repartition, i.e., --- increase the number of slices. -SELECT * FROM attach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', repartition => false); -WARNING: attaching data node is deprecated -WARNING: insufficient number of partitions for dimension "__region" - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 4 | 4 | db_dist_hypertable_2 -(1 row) - --- Number of slices should not be increased -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Manually increase the number of partitions -SELECT * FROM set_number_partitions('"Table\\Schema"."Param_Table"', 4); - set_number_partitions ------------------------ - -(1 row) - --- Verify hypertables on all data nodes -SELECT * FROM _timescaledb_catalog.hypertable; - id | schema_name | table_name | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size | compression_state | compressed_hypertable_id | replication_factor | status -----+---------------+-----------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+-------------------+--------------------------+--------------------+-------- - 1 | public | disttable | _timescaledb_internal | _dist_hyper_1 | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 1 | 0 - 2 | public | underreplicated | _timescaledb_internal | _dist_hyper_2 | 1 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 4 | 0 - 4 | Table\\Schema | Param_Table | T3sTSch | test*pre_ | 2 | _timescaledb_functions | calculate_chunk_interval | 0 | 0 | | 2 | 0 -(3 rows) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+--------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 4 | _timescaledb_functions | get_partition_hash | | | | -(5 rows) - -SELECT * FROM test.show_triggers('"Table\\Schema"."Param_Table"'); - Trigger | Type | Function --------------------+------+--------------------------------------- - ts_insert_blocker | 7 | _timescaledb_functions.insert_blocker -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.hypertable; -SELECT * FROM _timescaledb_catalog.dimension; -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_1]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_1]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_2]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 4|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_2]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.hypertable -NOTICE: [db_dist_hypertable_3]: -id|schema_name |table_name |associated_schema_name|associated_table_prefix|num_dimensions|chunk_sizing_func_schema|chunk_sizing_func_name |chunk_target_size|compression_state|compressed_hypertable_id|replication_factor|status ---+-------------+---------------+----------------------+-----------------------+--------------+------------------------+------------------------+-----------------+-----------------+------------------------+------------------+------ - 1|public |disttable |_timescaledb_internal |_dist_hyper_1 | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 2|public |underreplicated|_timescaledb_internal |_dist_hyper_2 | 1|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 - 3|Table\\Schema|Param_Table |T3sTSch |test*pre_ | 2|_timescaledb_functions |calculate_chunk_interval| 0| 0| | -1| 0 -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid -NOTICE: [db_dist_hypertable_3]: -tgname |tgtype|tgfoid ------------------+------+------------------------------------- -ts_insert_blocker| 7|_timescaledb_functions.insert_blocker -(1 row) - - - remote_exec -------------- - -(1 row) - --- Verify that repartitioning works as expected on detach_data_node -SELECT * FROM detach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"', repartition => true); -WARNING: detaching data node is deprecated -NOTICE: the number of partitions in dimension "__region" of hypertable "Param_Table" was decreased to 2 - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, repartition => false); -WARNING: detaching data node is deprecated -WARNING: insufficient number of data nodes for distributed hypertable "Param_Table" - detach_data_node ------------------- - 1 -(1 row) - -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - table_name | column_name | num_slices --------------+------------------+------------ - Param_Table | __region | 2 - Param_Table | time Col %#^#@$# | -(2 rows) - --- Test multi-dimensional hypertable. The add_dimension() command --- should be propagated to backends. -CREATE TABLE dimented_table (time timestamptz, column1 int, column2 timestamptz, column3 int); -SELECT * FROM create_distributed_hypertable('dimented_table', 'time', partitioning_column => 'column1', number_partitions => 4, replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1']); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 5 | public | dimented_table | t -(1 row) - --- Create one chunk to block add_dimension -INSERT INTO dimented_table VALUES('2017-01-01 06:01', 1, '2017-01-01 08:01', 1); -CREATE VIEW dimented_table_slices AS -SELECT c.id AS chunk_id, c.hypertable_id, ds.dimension_id, cc.dimension_slice_id, c.schema_name AS - chunk_schema, c.table_name AS chunk_table, ds.range_start, ds.range_end -FROM _timescaledb_catalog.chunk c -INNER JOIN _timescaledb_catalog.hypertable h ON (c.hypertable_id = h.id) -INNER JOIN _timescaledb_catalog.dimension td ON (h.id = td.hypertable_id) -INNER JOIN _timescaledb_catalog.dimension_slice ds ON (ds.dimension_id = td.id) -INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.dimension_slice_id = ds.id AND cc.chunk_id = c.id) -WHERE h.table_name = 'dimented_table' -ORDER BY c.id, ds.dimension_id; -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+------------------ - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 -(2 rows) - --- add_dimension() with existing data -SELECT * FROM add_dimension('dimented_table', 'column2', chunk_time_interval => interval '1 week'); -NOTICE: adding not-null constraint to column "column2" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 9 | public | dimented_table | column2 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(3 rows) - -SELECT * FROM add_dimension('dimented_table', 'column3', 4, partitioning_func => '_timescaledb_functions.get_partition_for_key'); - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+----------------+-------------+--------- - 10 | public | dimented_table | column3 | t -(1 row) - -SELECT * FROM dimented_table_slices; - chunk_id | hypertable_id | dimension_id | dimension_slice_id | chunk_schema | chunk_table | range_start | range_end -----------+---------------+--------------+--------------------+-----------------------+------------------------+----------------------+--------------------- - 11 | 5 | 7 | 8 | _timescaledb_internal | _dist_hyper_5_11_chunk | 1482969600000000 | 1483574400000000 - 11 | 5 | 8 | 9 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 536870911 - 11 | 5 | 9 | 10 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 - 11 | 5 | 10 | 11 | _timescaledb_internal | _dist_hyper_5_11_chunk | -9223372036854775808 | 9223372036854775807 -(4 rows) - -SELECT * FROM dimented_table ORDER BY time; - time | column1 | column2 | column3 -------------------------------+---------+------------------------------+--------- - Sun Jan 01 06:01:00 2017 PST | 1 | Sun Jan 01 08:01:00 2017 PST | 1 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - -SELECT * FROM attach_data_node(:'DATA_NODE_2', 'dimented_table'); -WARNING: attaching data node is deprecated - hypertable_id | node_hypertable_id | node_name ----------------+--------------------+---------------------- - 5 | 5 | db_dist_hypertable_2 -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension; - id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | compress_interval_length | integer_now_func_schema | integer_now_func -----+---------------+------------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+--------------------------+-------------------------+------------------ - 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | | - 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | | - 2 | 1 | device | integer | f | 3 | _timescaledb_functions | get_partition_hash | | | | - 5 | 4 | time Col %#^#@$# | timestamp with time zone | t | | | | 604800000000 | | | - 6 | 4 | __region | text | f | 2 | _timescaledb_functions | get_partition_hash | | | | - 7 | 5 | time | timestamp with time zone | t | | | | 604800000000 | | | - 8 | 5 | column1 | integer | f | 4 | _timescaledb_functions | get_partition_hash | | | | - 9 | 5 | column2 | timestamp with time zone | t | | | | 604800000000 | | | - 10 | 5 | column3 | integer | f | 4 | _timescaledb_functions | get_partition_for_key | | | | -(9 rows) - --- ensure data node has new dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.dimension; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time |timestamp with time zone|t | | | | 604800000000| | | - 7| 4|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 4|column2 |timestamp with time zone|t | | | | 604800000000| | | - 9| 4|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+---------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash | | | | - 6| 4|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 7| 4|__region |text |f | 4|_timescaledb_functions |get_partition_hash | | | | - 8| 5|time |timestamp with time zone|t | | | | 604800000000| | | - 9| 5|column1 |integer |f | 4|_timescaledb_functions |get_partition_hash | | | | -10| 5|column2 |timestamp with time zone|t | | | | 604800000000| | | -11| 5|column3 |integer |f | 4|_timescaledb_functions |get_partition_for_key| | | | -(9 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM _timescaledb_catalog.dimension -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name |column_type |aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+----------------+------------------------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- - 1| 1|time |timestamp with time zone|t | | | | 604800000000| | | - 3| 2|time |timestamp with time zone|t | | | | 604800000000| | | - 2| 1|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | - 4| 3|time Col %#^#@$#|timestamp with time zone|t | | | | 604800000000| | | - 5| 3|__region |text |f | 4|_timescaledb_functions |get_partition_hash| | | | -(5 rows) - - - remote_exec -------------- - -(1 row) - ---test per-data node queries --- Create some chunks through insertion -CREATE TABLE disttable_replicated(time timestamptz PRIMARY KEY, device int CHECK (device > 0), temp float, "Color" int); -SELECT * FROM create_hypertable('disttable_replicated', 'time', replication_factor => 2); - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------------+--------- - 6 | public | disttable_replicated | t -(1 row) - -INSERT INTO disttable_replicated VALUES - ('2017-01-01 06:01', 1, 1.1, 1), - ('2017-01-01 08:01', 1, 1.2, 2), - ('2018-01-02 08:01', 2, 1.3, 3), - ('2019-01-01 09:11', 3, 2.1, 4), - ('2020-01-01 06:01', 5, 1.1, 10), - ('2020-01-01 08:01', 6, 1.2, 11), - ('2021-01-02 08:01', 7, 1.3, 12), - ('2022-01-01 09:11', 8, 2.1, 13); -SELECT * FROM disttable_replicated; - time | device | temp | Color -------------------------------+--------+------+------- - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 | 1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 | 2 - Wed Jan 01 06:01:00 2020 PST | 5 | 1.1 | 10 - Wed Jan 01 08:01:00 2020 PST | 6 | 1.2 | 11 - Tue Jan 02 08:01:00 2018 PST | 2 | 1.3 | 3 - Sat Jan 02 08:01:00 2021 PST | 7 | 1.3 | 12 - Tue Jan 01 09:11:00 2019 PST | 3 | 2.1 | 4 - Sat Jan 01 09:11:00 2022 PST | 8 | 2.1 | 13 -(8 rows) - -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---guc disables the optimization -SET timescaledb.enable_per_data_node_queries = FALSE; -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------- - Append (actual rows=8 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_12_chunk."time", _dist_hyper_6_12_chunk.device, _dist_hyper_6_12_chunk.temp, _dist_hyper_6_12_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_12_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_13_chunk."time", _dist_hyper_6_13_chunk.device, _dist_hyper_6_13_chunk.temp, _dist_hyper_6_13_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_13_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_14_chunk."time", _dist_hyper_6_14_chunk.device, _dist_hyper_6_14_chunk.temp, _dist_hyper_6_14_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_14_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk (actual rows=2 loops=1) - Output: _dist_hyper_6_15_chunk."time", _dist_hyper_6_15_chunk.device, _dist_hyper_6_15_chunk.temp, _dist_hyper_6_15_chunk."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_15_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_16_chunk."time", _dist_hyper_6_16_chunk.device, _dist_hyper_6_16_chunk.temp, _dist_hyper_6_16_chunk."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_16_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk (actual rows=1 loops=1) - Output: _dist_hyper_6_17_chunk."time", _dist_hyper_6_17_chunk.device, _dist_hyper_6_17_chunk.temp, _dist_hyper_6_17_chunk."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color" FROM _timescaledb_internal._dist_hyper_6_17_chunk -(31 rows) - -SET timescaledb.enable_per_data_node_queries = TRUE; ---test WHERE clause -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=0 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND ((temp > 2::double precision)) -(21 rows) - ---test OR -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0 or "Color" = 11; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=3 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=3 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=1 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) AND (((temp > 2::double precision) OR ("Color" = 11))) -(21 rows) - ---test some chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2018-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=2 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=2 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=2 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=0 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6]) AND (("time" < '2018-01-01 09:11:00-08'::timestamp with time zone)) -(15 rows) - ---test all chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2002-01-01 09:11'; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=0 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - One-Time Filter: false -(3 rows) - ---test cte -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH cte AS ( - SELECT * FROM disttable_replicated -) -SELECT * FROM cte; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=8 loops=1) - Output: disttable_replicated."time", disttable_replicated.device, disttable_replicated.temp, disttable_replicated."Color" - -> Append (actual rows=8 loops=1) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_1 (actual rows=4 loops=1) - Output: disttable_replicated_1."time", disttable_replicated_1.device, disttable_replicated_1.temp, disttable_replicated_1."Color" - Data node: db_dist_hypertable_1 - Fetcher Type: COPY - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2."time", disttable_replicated_2.device, disttable_replicated_2.temp, disttable_replicated_2."Color" - Data node: db_dist_hypertable_2 - Fetcher Type: COPY - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_3 (actual rows=2 loops=1) - Output: disttable_replicated_3."time", disttable_replicated_3.device, disttable_replicated_3.temp, disttable_replicated_3."Color" - Data node: db_dist_hypertable_3 - Fetcher Type: COPY - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT "time", device, temp, "Color" FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) -(21 rows) - ---queries that involve updates/inserts are not optimized -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH devices AS ( - SELECT DISTINCT device FROM disttable_replicated ORDER BY device -) -UPDATE disttable_replicated SET device = 2 WHERE device = (SELECT device FROM devices LIMIT 1); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Update on public.disttable_replicated (actual rows=0 loops=1) - Update on public.disttable_replicated disttable_replicated_1 - Foreign Update on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_2 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_12_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_3 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_13_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_4 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_14_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_5 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_15_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_6 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_16_chunk SET device = $2 WHERE ctid = $1 - Foreign Update on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_7 - Remote SQL: UPDATE _timescaledb_internal._dist_hyper_6_17_chunk SET device = $2 WHERE ctid = $1 - InitPlan 1 (returns $0) - -> Limit (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Unique (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: disttable_replicated_8.device - -> Merge Append (actual rows=1 loops=1) - Sort Key: disttable_replicated_9.device - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_9 (actual rows=1 loops=1) - Output: disttable_replicated_9.device - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_12_chunk, _dist_hyper_6_15_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_10 (actual rows=1 loops=1) - Output: disttable_replicated_10.device - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_13_chunk, _dist_hyper_6_16_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.disttable_replicated disttable_replicated_11 (actual rows=1 loops=1) - Output: disttable_replicated_11.device - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Chunks: _dist_hyper_6_14_chunk, _dist_hyper_6_17_chunk - Remote SQL: SELECT DISTINCT device FROM public.disttable_replicated WHERE _timescaledb_functions.chunks_in(public.disttable_replicated.*, ARRAY[6, 8]) ORDER BY device ASC NULLS LAST - -> Result (actual rows=2 loops=1) - Output: 2, disttable_replicated.tableoid, disttable_replicated.ctid, (NULL::record) - -> Append (actual rows=2 loops=1) - -> Seq Scan on public.disttable_replicated disttable_replicated_1 (actual rows=0 loops=1) - Output: disttable_replicated_1.tableoid, disttable_replicated_1.ctid, NULL::record - Filter: (disttable_replicated_1.device = $0) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_12_chunk disttable_replicated_2 (actual rows=2 loops=1) - Output: disttable_replicated_2.tableoid, disttable_replicated_2.ctid, disttable_replicated_2.* - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_12_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_13_chunk disttable_replicated_3 (actual rows=0 loops=1) - Output: disttable_replicated_3.tableoid, disttable_replicated_3.ctid, disttable_replicated_3.* - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_13_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_14_chunk disttable_replicated_4 (actual rows=0 loops=1) - Output: disttable_replicated_4.tableoid, disttable_replicated_4.ctid, disttable_replicated_4.* - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_14_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_15_chunk disttable_replicated_5 (actual rows=0 loops=1) - Output: disttable_replicated_5.tableoid, disttable_replicated_5.ctid, disttable_replicated_5.* - Data node: db_dist_hypertable_1 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_15_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_16_chunk disttable_replicated_6 (actual rows=0 loops=1) - Output: disttable_replicated_6.tableoid, disttable_replicated_6.ctid, disttable_replicated_6.* - Data node: db_dist_hypertable_2 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_16_chunk WHERE ((device = $1::integer)) - -> Foreign Scan on _timescaledb_internal._dist_hyper_6_17_chunk disttable_replicated_7 (actual rows=0 loops=1) - Output: disttable_replicated_7.tableoid, disttable_replicated_7.ctid, disttable_replicated_7.* - Data node: db_dist_hypertable_3 - Fetcher Type: Cursor - Remote SQL: SELECT "time", device, temp, "Color", ctid FROM _timescaledb_internal._dist_hyper_6_17_chunk WHERE ((device = $1::integer)) -(77 rows) - --- Test inserts with smaller batch size and more tuples to reach full --- batch -SET timescaledb.max_insert_batch_size=4; -CREATE TABLE twodim (time timestamptz DEFAULT '2019-02-10 10:11', "Color" int DEFAULT 11 CHECK ("Color" > 0), temp float DEFAULT 22.1); --- Create a replicated table to ensure we handle that case correctly --- with batching -SELECT * FROM create_hypertable('twodim', 'time', 'Color', 3, replication_factor => 2, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2',:'DATA_NODE_3']); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 7 | public | twodim | t -(1 row) - -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------+-------+------ -(0 rows) - --- INSERT enough data to stretch across multiple batches per --- data node. Also return a system column. Although we write tuples to --- multiple data nodes, the returned tuple should only be the ones in the --- original insert statement (without the replica tuples). -WITH result AS ( - INSERT INTO twodim VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1) - RETURNING tableoid = 'twodim'::regclass AS is_tableoid, time, temp, "Color" -) SELECT * FROM result ORDER BY time; - is_tableoid | time | temp | Color --------------+------------------------------+------+------- - t | Wed Feb 01 06:01:00 2017 PST | 1.1 | 1 - t | Wed Feb 01 08:01:00 2017 PST | 1.2 | 1 - t | Fri Feb 02 08:01:00 2018 PST | 1.3 | 2 - t | Fri Feb 01 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 09:11:00 2019 PST | 2.1 | 3 - t | Sat Feb 02 10:01:00 2019 PST | 1.2 | 5 - t | Sun Feb 03 11:11:00 2019 PST | 3.5 | 6 - t | Mon Feb 04 08:21:00 2019 PST | 6.6 | 4 - t | Mon Feb 04 10:11:00 2019 PST | 7.4 | 7 - t | Mon Feb 04 12:11:00 2019 PST | 2.1 | 8 - t | Tue Feb 05 13:31:00 2019 PST | 6.3 | 8 - t | Wed Feb 06 01:13:00 2019 PST | 7.9 | 7 - t | Wed Feb 06 02:11:00 2019 PST | 1.8 | 5 - t | Wed Feb 06 19:24:00 2019 PST | 5.9 | 9 - t | Thu Feb 07 09:33:00 2019 PST | 9.5 | 7 - t | Thu Feb 07 18:44:00 2019 PST | 9.7 | 5 - t | Thu Feb 07 20:24:00 2019 PST | | 6 - t | Fri Feb 08 08:54:00 2019 PST | 7.3 | 1 - t | Fri Feb 08 18:14:00 2019 PST | 8.2 | 4 - t | Sat Feb 09 19:23:00 2019 PST | 9.1 | 8 -(20 rows) - --- Test insert with default values and a batch size of 1. -SET timescaledb.max_insert_batch_size=1; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim DEFAULT VALUES; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - Batch size: 1 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Custom Scan (ChunkDispatch) - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision - -> Result - Output: 'Sun Feb 10 10:11:00 2019 PST'::timestamp with time zone, 11, '22.1'::double precision -(12 rows) - -INSERT INTO twodim DEFAULT VALUES; --- Reset the batch size -SET timescaledb.max_insert_batch_size=4; --- Constraint violation error check --- --- Execute and filter mentioned data node name in the error message. -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ INSERT INTO twodim VALUES ('2019-02-10 17:54', 0, 10.2) $$, :'TEST_DBNAME'); -ERROR: [db_dist_hypertable_x]: new row for relation "_dist_hyper_7_23_chunk" violates check constraint "twodim_Color_check" -\set ON_ERROR_STOP 1 --- Disable batching, reverting to FDW tuple-by-tuple inserts. --- First EXPLAIN with batching turned on. -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.twodim - -> Custom Scan (DataNodeDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - Batch size: 4 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3), ..., ($10, $11, $12) - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(12 rows) - -SET timescaledb.max_insert_batch_size=0; --- Compare without batching -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - QUERY PLAN ----------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) - Insert on distributed hypertable public.twodim - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - Remote SQL: INSERT INTO public.twodim("time", "Color", temp) VALUES ($1, $2, $3) - -> Insert on public.twodim - -> Custom Scan (ChunkDispatch) - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 - -> Values Scan on "*VALUES*" - Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3 -(9 rows) - --- Insert without batching -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when multiple dimensions are involved. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT * FROM twodim -ORDER BY time; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: twodim."time", twodim."Color", twodim.temp - -> Merge Append - Sort Key: twodim_1."time" - -> Custom Scan (DataNodeScan) on public.twodim twodim_1 - Output: twodim_1."time", twodim_1."Color", twodim_1.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_7_18_chunk, _dist_hyper_7_22_chunk, _dist_hyper_7_25_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12, 14]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_18_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_18_chunk - Output: _dist_hyper_7_18_chunk."time", _dist_hyper_7_18_chunk."Color", _dist_hyper_7_18_chunk.temp - -> Index Scan Backward using _dist_hyper_7_22_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_22_chunk - Output: _dist_hyper_7_22_chunk."time", _dist_hyper_7_22_chunk."Color", _dist_hyper_7_22_chunk.temp - -> Index Scan Backward using _dist_hyper_7_25_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_25_chunk - Output: _dist_hyper_7_25_chunk."time", _dist_hyper_7_25_chunk."Color", _dist_hyper_7_25_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_2 - Output: twodim_2."time", twodim_2."Color", twodim_2.temp - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_7_19_chunk, _dist_hyper_7_21_chunk, _dist_hyper_7_24_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 11, 13]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_19_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_19_chunk - Output: _dist_hyper_7_19_chunk."time", _dist_hyper_7_19_chunk."Color", _dist_hyper_7_19_chunk.temp - -> Index Scan Backward using _dist_hyper_7_21_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_21_chunk - Output: _dist_hyper_7_21_chunk."time", _dist_hyper_7_21_chunk."Color", _dist_hyper_7_21_chunk.temp - -> Index Scan Backward using _dist_hyper_7_24_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_24_chunk - Output: _dist_hyper_7_24_chunk."time", _dist_hyper_7_24_chunk."Color", _dist_hyper_7_24_chunk.temp - - -> Custom Scan (DataNodeScan) on public.twodim twodim_3 - Output: twodim_3."time", twodim_3."Color", twodim_3.temp - Data node: db_dist_hypertable_3 - Chunks: _dist_hyper_7_20_chunk, _dist_hyper_7_23_chunk - Remote SQL: SELECT "time", "Color", temp FROM public.twodim WHERE _timescaledb_functions.chunks_in(public.twodim.*, ARRAY[10, 12]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Custom Scan (ChunkAppend) on public.twodim - Output: twodim."time", twodim."Color", twodim.temp - Order: twodim."time" - Startup Exclusion: false - Runtime Exclusion: false - -> Index Scan Backward using _dist_hyper_7_20_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_20_chunk - Output: _dist_hyper_7_20_chunk."time", _dist_hyper_7_20_chunk."Color", _dist_hyper_7_20_chunk.temp - -> Index Scan Backward using _dist_hyper_7_23_chunk_twodim_time_idx on _timescaledb_internal._dist_hyper_7_23_chunk - Output: _dist_hyper_7_23_chunk."time", _dist_hyper_7_23_chunk."Color", _dist_hyper_7_23_chunk.temp - -(56 rows) - -SET timescaledb.enable_remote_explain = OFF; --- Check results -SELECT * FROM twodim -ORDER BY time; - time | Color | temp -------------------------------+-------+------ - Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - Thu Feb 07 20:24:00 2019 PST | 6 | - Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 - Sun Feb 10 10:11:00 2019 PST | 11 | 22.1 - Sun Feb 10 16:23:00 2019 PST | 5 | 7.1 - Sun Feb 10 17:11:00 2019 PST | 7 | 3.2 -(23 rows) - -SELECT count(*) FROM twodim; - count -------- - 23 -(1 row) - --- Show distribution across data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM twodim -ORDER BY time; -SELECT count(*) FROM twodim; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_1]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -(12 rows) - - -NOTICE: [db_dist_hypertable_1]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_1]: -count ------ - 12 -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_2]: -time |Color|temp -----------------------------+-----+---- -Wed Feb 01 06:01:00 2017 PST| 1| 1.1 -Wed Feb 01 08:01:00 2017 PST| 1| 1.2 -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Sun Feb 03 11:11:00 2019 PST| 6| 3.5 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Mon Feb 04 12:11:00 2019 PST| 8| 2.1 -Tue Feb 05 13:31:00 2019 PST| 8| 6.3 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Thu Feb 07 20:24:00 2019 PST| 6| -Fri Feb 08 08:54:00 2019 PST| 1| 7.3 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sat Feb 09 19:23:00 2019 PST| 8| 9.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(19 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_2]: -count ------ - 19 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT * FROM twodim -ORDER BY time -NOTICE: [db_dist_hypertable_3]: -time |Color|temp -----------------------------+-----+---- -Fri Feb 02 08:01:00 2018 PST| 2| 1.3 -Fri Feb 01 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 09:11:00 2019 PST| 3| 2.1 -Sat Feb 02 10:01:00 2019 PST| 5| 1.2 -Mon Feb 04 08:21:00 2019 PST| 4| 6.6 -Mon Feb 04 10:11:00 2019 PST| 7| 7.4 -Wed Feb 06 01:13:00 2019 PST| 7| 7.9 -Wed Feb 06 02:11:00 2019 PST| 5| 1.8 -Wed Feb 06 19:24:00 2019 PST| 9| 5.9 -Thu Feb 07 09:33:00 2019 PST| 7| 9.5 -Thu Feb 07 18:44:00 2019 PST| 5| 9.7 -Fri Feb 08 18:14:00 2019 PST| 4| 8.2 -Sun Feb 10 10:11:00 2019 PST| 11|22.1 -Sun Feb 10 16:23:00 2019 PST| 5| 7.1 -Sun Feb 10 17:11:00 2019 PST| 7| 3.2 -(15 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT count(*) FROM twodim -NOTICE: [db_dist_hypertable_3]: -count ------ - 15 -(1 row) - - - remote_exec -------------- - -(1 row) - --- Distributed table with custom type that has no binary output -CREATE TABLE disttable_with_ct(time timestamptz, txn_id rxid, val float, info text); -SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 2); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------------+--------- - 8 | public | disttable_with_ct | t -(1 row) - --- Insert data with custom type -INSERT INTO disttable_with_ct VALUES - ('2019-01-01 01:01', 'ts-1-10-20-30', 1.1, 'a'), - ('2019-01-01 01:02', 'ts-1-11-20-30', 2.0, repeat('abc', 1000000)); -- TOAST --- Test queries on distributed table with custom type -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - -SET timescaledb.enable_connection_binary_data=false; -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:01:00 2019 PST | ts-1-10-20-30 | 1.1 | a - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(2 rows) - --- Test DELETE with replication -DELETE FROM disttable_with_ct WHERE info = 'a'; --- Check if row is gone -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - time | txn_id | val | substring -------------------------------+---------------+-----+---------------------- - Tue Jan 01 01:02:00 2019 PST | ts-1-11-20-30 | 2 | abcabcabcabcabcabcab -(1 row) - --- Connect to data nodes to see if data is gone -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_1]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_2]: -time|txn_id|val|substring -----+------+---+--------- -(0 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct -NOTICE: [db_dist_hypertable_3]: -time |txn_id |val|substring -----------------------------+-------------+---+-------------------- -Tue Jan 01 01:02:00 2019 PST|ts-1-11-20-30| 2|abcabcabcabcabcabcab -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test single quote in names -SET SCHEMA 'single''schema'; -CREATE TABLE "disttable'quote"(time timestamptz, "device'quote" int, val float, info text); -SELECT public.create_distributed_hypertable( - 'disttable''quote', 'time', 'device''quote', data_nodes => ARRAY[:'DATA_NODE_1'] -); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------------- - (9,single'schema,disttable'quote,t) -(1 row) - -SET SCHEMA 'public'; -CREATE TABLE disttable_drop_chunks(time timestamptz, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable_drop_chunks', 'time', 'device', number_partitions => 3, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------------+--------- - 10 | public | disttable_drop_chunks | t -(1 row) - -INSERT INTO disttable_drop_chunks VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5); --- Show chunks on access node -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 27 | 10 | _timescaledb_internal | _dist_hyper_10_27_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 28 | 10 | _timescaledb_internal | _dist_hyper_10_28_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 29 | 10 | _timescaledb_internal | _dist_hyper_10_29_chunk | f | {"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(6 rows) - --- Show chunks on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 16| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 17| 9|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 9|_timescaledb_internal|_dist_hyper_10_27_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [-9223372036854775808, 715827882]} - 16| 9|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 15| 7|_timescaledb_internal|_dist_hyper_10_28_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [1431655764, 9223372036854775807]} - 16| 7|_timescaledb_internal|_dist_hyper_10_29_chunk|r |{"time": [1482969600000000, 1483574400000000], "device": [715827882, 1431655764]} - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM drop_chunks('disttable_drop_chunks', older_than => '2018-01-01'::timestamptz); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_27_chunk - _timescaledb_internal._dist_hyper_10_28_chunk - _timescaledb_internal._dist_hyper_10_29_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------------------------------+--------+------- - Mon Jul 02 08:01:00 2018 PDT | 87 | 2 - Sun Jul 01 06:01:00 2018 PDT | 13 | 1 - Sun Jul 01 09:11:00 2018 PDT | 90 | 3 - Sun Jul 01 08:01:00 2018 PDT | 29 | 2 -(4 rows) - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - chunk_id | hypertable_id | schema_name | table_name | relkind | slices -----------+---------------+-----------------------+-------------------------+---------+--------------------------------------------------------------------------------------------- - 30 | 10 | _timescaledb_internal | _dist_hyper_10_30_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 31 | 10 | _timescaledb_internal | _dist_hyper_10_31_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 32 | 10 | _timescaledb_internal | _dist_hyper_10_32_chunk | f | {"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(3 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 18| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 19| 9|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 9|_timescaledb_internal|_dist_hyper_10_30_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [-9223372036854775808, 715827882]} - 18| 9|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 17| 7|_timescaledb_internal|_dist_hyper_10_31_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [715827882, 1431655764]} - 18| 7|_timescaledb_internal|_dist_hyper_10_32_chunk|r |{"time": [1530144000000000, 1530748800000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- test passing newer_than as interval -SELECT * FROM drop_chunks('disttable_drop_chunks', newer_than => interval '10 years'); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_10_30_chunk - _timescaledb_internal._dist_hyper_10_31_chunk - _timescaledb_internal._dist_hyper_10_32_chunk -(3 rows) - -SELECT * FROM disttable_drop_chunks; - time | device | color -------+--------+------- -(0 rows) - -CREATE TABLE "weird nAme\\#^."(time bigint, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('"weird nAme\\#^."', 'time', 'device', 3, chunk_time_interval => 100, replication_factor => 2); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-----------------+--------- - 11 | public | weird nAme\\#^. | t -(1 row) - -INSERT INTO "weird nAme\\#^." VALUES - (300, 1, 1.1), - (400, 3, 2.1), - (350, 1, 1.2); -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- - 300 | 1 | 1 - 350 | 1 | 1 - 400 | 3 | 2 -(3 rows) - --- drop chunks using bigint as time -SELECT * FROM drop_chunks('"weird nAme\\#^."', older_than => 1000); - drop_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_11_33_chunk - _timescaledb_internal._dist_hyper_11_34_chunk -(2 rows) - -SELECT * FROM "weird nAme\\#^."; - time | device | color -------+--------+------- -(0 rows) - ------------------------------------------------------------------------------------------ --- Test that settings on hypertables are distributed to data nodes ------------------------------------------------------------------------------------------ -DROP TABLE disttable CASCADE; -CREATE TABLE disttable (time bigint, device int, temp float); -SELECT create_distributed_hypertable('disttable', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (12,public,disttable,t) -(1 row) - --- Show the dimension configuration on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -20| 11|time |bigint |t | | | | 1000000| | | -(1 row) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func|interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+-----------------+---------------+------------------------+-----------------------+---------------- -14| 9|time |bigint |t | | | | 1000000| | | -(1 row) - - - remote_exec -------------- - -(1 row) - --- Test adding a space dimension. Should apply to data nodes as --- well. We're setting num_partitions lower than the number of servers --- and expect a warning. -SELECT * FROM add_dimension('disttable', 'device', 1, partitioning_func => '_timescaledb_functions.get_partition_hash'); -WARNING: insufficient number of partitions for dimension "device" - dimension_id | schema_name | table_name | column_name | created ---------------+-------------+------------+-------------+--------- - 22 | public | disttable | device | t -(1 row) - -CREATE INDEX disttable_device_time_idx ON disttable (device, time); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 1000000| | | -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 1|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 1000000| | | -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Show that changing dimension settings apply to data nodes -SELECT * FROM set_chunk_time_interval('disttable', 2000000000::bigint); - set_chunk_time_interval -------------------------- - -(1 row) - -SELECT * FROM set_number_partitions('disttable', 3); - set_number_partitions ------------------------ - -(1 row) - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT' -$$); -SELECT * FROM set_integer_now_func('disttable', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - --- Show changes to dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_1]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_2]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_2]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -21| 11|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -20| 11|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable' -NOTICE: [db_dist_hypertable_3]: -id|hypertable_id|column_name|column_type|aligned|num_slices|partitioning_func_schema|partitioning_func |interval_length|compress_interval_length|integer_now_func_schema|integer_now_func ---+-------------+-----------+-----------+-------+----------+------------------------+------------------+---------------+------------------------+-----------------------+---------------- -15| 9|device |integer |f | 3|_timescaledb_functions |get_partition_hash| | | | -14| 9|time |bigint |t | | | | 2000000000| |public |dummy_now -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Tests for using tablespaces with distributed hypertables -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE TABLESPACE :TABLESPACE_1 OWNER :ROLE_1 LOCATION :'spc1path'; -CREATE TABLESPACE :TABLESPACE_2 OWNER :ROLE_1 LOCATION :'spc2path'; -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_1', 'disttable'); -ERROR: tablespace "db_dist_hypertable_1" is not attached to hypertable "disttable" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable'); - detach_tablespaces --------------------- - 0 -(1 row) - --- Continue to use previously attached tablespace, but block attach/detach -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_distributed_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (13,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_13_35_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable2'); - detach_tablespaces --------------------- - 0 -(1 row) - -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - --- Ensure tablespace API works for data nodes -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT detach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec($$ -SELECT detach_tablespaces('disttable2'); -$$); -DROP TABLE disttable2; -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint, replication_factor => 1); -NOTICE: adding not-null constraint to column "time" - create_hypertable --------------------------- - (14,public,disttable2,t) -(1 row) - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - show_chunks ------------------------------------------------ - _timescaledb_internal._dist_hyper_14_36_chunk -(1 row) - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - reltablespace ---------------- - 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: cannot attach tablespace to distributed hypertable -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -ERROR: tablespace "db_dist_hypertable_2" is not attached to hypertable "disttable2" -\set ON_ERROR_STOP 1 -SELECT * FROM show_tablespaces('disttable2'); - show_tablespaces ------------------- -(0 rows) - -DROP TABLE disttable2; -DROP TABLESPACE :TABLESPACE_1; -DROP TABLESPACE :TABLESPACE_2; --- Make sure table qualified name is used in chunks_in function. Otherwise having a table name same as a column name might yield an error -CREATE TABLE dist_device(time timestamptz, dist_device int, temp float); -SELECT * FROM create_distributed_hypertable('dist_device', 'time'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 15 | public | dist_device | t -(1 row) - -INSERT INTO dist_device VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2); -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM dist_device; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) -(5 rows) - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when only time partitioning is being used. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT "time", dist_device, temp FROM public.dist_device ORDER BY "time" ASC NULLS LAST; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.dist_device - Output: dist_device."time", dist_device.dist_device, dist_device.temp - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_15_37_chunk - Remote SQL: SELECT "time", dist_device, temp FROM public.dist_device WHERE _timescaledb_functions.chunks_in(public.dist_device.*, ARRAY[22]) ORDER BY "time" ASC NULLS LAST - Remote EXPLAIN: - Index Scan Backward using _dist_hyper_15_37_chunk_dist_device_time_idx on _timescaledb_internal._dist_hyper_15_37_chunk - Output: _dist_hyper_15_37_chunk."time", _dist_hyper_15_37_chunk.dist_device, _dist_hyper_15_37_chunk.temp - -(9 rows) - -SELECT * FROM dist_device; - time | dist_device | temp -------------------------------+-------------+------ - Sun Jan 01 06:01:00 2017 PST | 1 | 1.1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2.1 - Sun Jan 01 08:01:00 2017 PST | 1 | 1.2 -(3 rows) - --- Test estimating relation size without stats -CREATE TABLE hyper_estimate(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('hyper_estimate', 'time', 'device', number_partitions => 3, replication_factor => 1, chunk_time_interval => INTERVAL '7 days'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+----------------+--------- - 16 | public | hyper_estimate | t -(1 row) - --- This will enable us to more easily see estimates per chunk -SET timescaledb.enable_per_data_node_queries = false; --- Estimating chunk progress uses current timestamp so we override it for test purposes -SELECT test.tsl_override_current_timestamptz('2017-11-11 00:00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - --- Test estimates when backfilling. 3 chunks should be historical and 3 should be considered current when estimating. --- Note that estimate numbers are way off since we are using shared buffer size as starting point. This will not be --- an issue in 'production' like env since chunk size should be similar to shared buffer size. -INSERT INTO hyper_estimate VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); --- This will calculate the stats -ANALYZE hyper_estimate; -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..60021.38 rows=15 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) -(7 rows) - --- Let's insert data into a new chunk. This will result in chunk creation. -INSERT INTO hyper_estimate VALUES ('2019-11-11 06:01', 1, 1.1); --- We have stats for previous chunks so we can interpolate number of rows for the new chunk -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - QUERY PLAN ------------------------------------------------------------------------------------------- - Append (cost=10000.00..70023.31 rows=17 width=20) - -> Foreign Scan on _dist_hyper_16_38_chunk (cost=10000.00..10005.08 rows=4 width=20) - -> Foreign Scan on _dist_hyper_16_39_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_40_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_41_chunk (cost=10000.00..10003.04 rows=2 width=20) - -> Foreign Scan on _dist_hyper_16_42_chunk (cost=10000.00..10004.06 rows=3 width=20) - -> Foreign Scan on _dist_hyper_16_43_chunk (cost=10000.00..10002.02 rows=1 width=20) - -> Foreign Scan on _dist_hyper_16_44_chunk (cost=10000.00..10001.93 rows=2 width=20) -(8 rows) - -CREATE TABLE devices ( - device_id INTEGER PRIMARY KEY, - device_name VARCHAR(10) -); -CALL distributed_exec($$ - CREATE TABLE devices(device_id INTEGER PRIMARY KEY, device_name VARCHAR(10)) -$$); -INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765'); -CALL distributed_exec($$ - INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765') -$$); -CREATE TABLE hyper ( - time TIMESTAMPTZ NOT NULL, - device INTEGER REFERENCES devices(device_id), - temp FLOAT -); -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours' -); -WARNING: distributed hypertable is deprecated -WARNING: distributed hypertable "hyper" has a foreign key to a non-distributed table - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 17 | public | hyper | t -(1 row) - --- Inserting some values should succeed. -INSERT INTO hyper VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM hyper -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - time | device | avg_temp -------------------------------+--------+---------- - Sun Jan 01 07:00:00 2017 PST | 1 | 1.65 - Mon Jan 02 04:00:00 2017 PST | 2 | 1.4 - Mon Jan 02 07:00:00 2017 PST | 2 | 1.6 - Mon Jan 02 07:00:00 2017 PST | 1 | 1.3 - Tue Jan 03 01:00:00 2017 PST | 3 | 3 - Sat Jan 13 01:00:00 2018 PST | 2 | 1.4 - Sat Jan 13 04:00:00 2018 PST | 2 | 3 - Sat Jan 13 16:00:00 2018 PST | 3 | 2 -(8 rows) - --- Add some devices on the access node only. Inserts should then fail. -INSERT INTO devices VALUES (6, 'E999'); -\set ON_ERROR_STOP 0 -INSERT INTO hyper VALUES ('2017-01-01 06:01', 6, 1.1); -ERROR: [db_dist_hypertable_1]: insert or update on table "_dist_hyper_17_45_chunk" violates foreign key constraint "26_17_hyper_device_fkey" -\set ON_ERROR_STOP 1 --- Test alter replication factor with data -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Dimension partitions should be updated to account for replication --- to additional data nodes -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1} - hyper | 29 | 715827882 | {db_dist_hypertable_2} - hyper | 29 | 1431655764 | {db_dist_hypertable_3} -(3 rows) - -SELECT * FROM set_replication_factor('hyper', 3); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+------------------------------------------------------------------ - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3,db_dist_hypertable_1} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1,db_dist_hypertable_2} -(3 rows) - -INSERT INTO hyper VALUES ('2017-01-02 07:11', 1, 1.7); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+--------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} -(2 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} -(2 rows) - - - remote_exec -------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-02-01 06:01', 1, 5.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - table_name | dimension_id | range_start | data_nodes -------------+--------------+----------------------+--------------------------------------------- - hyper | 29 | -9223372036854775808 | {db_dist_hypertable_1,db_dist_hypertable_2} - hyper | 29 | 715827882 | {db_dist_hypertable_2,db_dist_hypertable_3} - hyper | 29 | 1431655764 | {db_dist_hypertable_3,db_dist_hypertable_1} -(3 rows) - -INSERT INTO hyper VALUES ('2017-03-01 06:01', 1, 15.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(4 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} -(3 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM set_replication_factor('hyper', replication_factor => 2); -WARNING: hypertable "hyper" is under-replicated - set_replication_factor ------------------------- - -(1 row) - -INSERT INTO hyper VALUES ('2017-04-01 06:01', 2, 45.1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_1]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 26| 16|_timescaledb_internal|_dist_hyper_17_45_chunk|r |{"time": [1483272000000000, 1483336800000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_46_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [-9223372036854775808, 715827882]} - 28| 16|_timescaledb_internal|_dist_hyper_17_49_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [-9223372036854775808, 715827882]} - 29| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 30| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_2]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 16|_timescaledb_internal|_dist_hyper_17_47_chunk|r |{"time": [1483336800000000, 1483401600000000], "device": [715827882, 1431655764]} - 24| 16|_timescaledb_internal|_dist_hyper_17_50_chunk|r |{"time": [1515801600000000, 1515866400000000], "device": [715827882, 1431655764]} - 25| 16|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 16|_timescaledb_internal|_dist_hyper_17_53_chunk|r |{"time": [1488326400000000, 1488391200000000], "device": [-9223372036854775808, 715827882]} - 27| 16|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper') -NOTICE: [db_dist_hypertable_3]: -chunk_id|hypertable_id|schema_name |table_name |relkind|slices ---------+-------------+---------------------+-----------------------+-------+------------------------------------------------------------------------------------------- - 23| 14|_timescaledb_internal|_dist_hyper_17_48_chunk|r |{"time": [1483401600000000, 1483466400000000], "device": [1431655764, 9223372036854775807]} - 24| 14|_timescaledb_internal|_dist_hyper_17_51_chunk|r |{"time": [1515866400000000, 1515931200000000], "device": [1431655764, 9223372036854775807]} - 25| 14|_timescaledb_internal|_dist_hyper_17_52_chunk|r |{"time": [1485928800000000, 1485993600000000], "device": [-9223372036854775808, 715827882]} - 26| 14|_timescaledb_internal|_dist_hyper_17_54_chunk|r |{"time": [1491048000000000, 1491112800000000], "device": [715827882, 1431655764]} -(4 rows) - - - remote_exec -------------- - -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('hyper', replication_factor => 4); -ERROR: replication factor too large for hypertable "hyper" -\set ON_ERROR_STOP 1 -DROP TABLE hyper; -CALL distributed_exec($$ - DROP TABLE devices; -$$); -DROP TABLE devices; --- Test storage options are distributed to data nodes --- --- Make sure that options used during CREATE TABLE WITH and CREATE INDEX WITH --- are properly distributed. --- -CREATE TABLE disttable_with_relopts_1(time timestamptz NOT NULL, device int) WITH (fillfactor=10); -CREATE TABLE disttable_with_relopts_2(time timestamptz NOT NULL, device int) WITH (fillfactor=10, parallel_workers=1); -CREATE TABLE disttable_with_relopts_3(time timestamptz NOT NULL, device int); -CREATE INDEX disttable_with_relopts_3_idx ON disttable_with_relopts_3(device) WITH (fillfactor=20); -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_1', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 18 | public | disttable_with_relopts_1 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_2', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 19 | public | disttable_with_relopts_2 | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_3', 'time'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------------------+--------- - 20 | public | disttable_with_relopts_3 | t -(1 row) - -INSERT INTO disttable_with_relopts_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -INSERT INTO disttable_with_relopts_2 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=10} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; - relname | reloptions ---------------------------+------------------------------------ - disttable_with_relopts_2 | {fillfactor=10,parallel_workers=1} -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_3 | -(1 row) - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; - relname | reloptions -------------------------------+----------------- - disttable_with_relopts_3_idx | {fillfactor=20} -(1 row) - --- Ensure reloptions are not set for distributed hypertable chunks on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_19_57_chunk | - _dist_hyper_19_58_chunk | -(2 rows) - --- Ensure parent tables has proper storage options -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+--------------- -disttable_with_relopts_1|{fillfactor=10} -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -------------------------+---------------------------------- -disttable_with_relopts_2|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Ensure index has proper storage options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions -----------------------------+--------------- -disttable_with_relopts_3_idx|{fillfactor=20} -(1 row) - - - remote_exec -------------- - -(1 row) - --- Make sure chunks derive parent reloptions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=10} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname|reloptions --------+---------- -(0 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_57_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname |reloptions ------------------------+---------------------------------- -_dist_hyper_19_58_chunk|{fillfactor=10,parallel_workers=1} -(1 row) - - - remote_exec -------------- - -(1 row) - --- ALTER TABLE SET/RESET support for distributed hypertable --- --- SET -ALTER TABLE disttable_with_relopts_1 SET (fillfactor=40); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+----------------- - disttable_with_relopts_1 | {fillfactor=40} -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_55_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+--------------- -_dist_hyper_18_56_chunk|{fillfactor=40} -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- RESET -ALTER TABLE disttable_with_relopts_1 RESET (fillfactor); -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - relname | reloptions ---------------------------+------------ - disttable_with_relopts_1 | -(1 row) - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - relname | reloptions --------------------------+------------ - _dist_hyper_18_55_chunk | - _dist_hyper_18_56_chunk | -(2 rows) - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_1]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_55_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_2]: -relname |reloptions ------------------------+---------- -_dist_hyper_18_56_chunk| -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname -NOTICE: [db_dist_hypertable_3]: -relname|reloptions --------+---------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_with_relopts_1; -DROP TABLE disttable_with_relopts_2; -DROP TABLE disttable_with_relopts_3; --- Test SERIAL type column support for distributed hypertables --- -CREATE TABLE disttable_serial(time timestamptz NOT NULL, device int, id1 SERIAL, id2 SMALLSERIAL, id3 BIGSERIAL); -SELECT create_distributed_hypertable('disttable_serial', 'time', 'device'); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable --------------------------------- - (21,public,disttable_serial,t) -(1 row) - --- Show created columns (AN and DN tables must be exact) -SELECT * FROM test.show_columns('disttable_serial'); - Column | Type | NotNull ---------+--------------------------+--------- - time | timestamp with time zone | t - device | integer | f - id1 | integer | t - id2 | smallint | t - id3 | bigint | t -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * FROM test.show_columns('disttable_serial'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_1]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_2]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * FROM test.show_columns('disttable_serial') -NOTICE: [db_dist_hypertable_3]: -Column|Type |NotNull -------+------------------------+------- -time |timestamp with time zone|t -device|integer |f -id1 |integer |t -id2 |smallint |t -id3 |bigint |t -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure DEFAULT expression is applied on the AN only -SELECT column_name, column_default -FROM information_schema.columns -WHERE table_name = 'disttable_serial'; - column_name | column_default --------------+----------------------------------------------- - time | - device | - id1 | nextval('disttable_serial_id1_seq'::regclass) - id2 | nextval('disttable_serial_id2_seq'::regclass) - id3 | nextval('disttable_serial_id3_seq'::regclass) -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial'; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_1]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_2]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - -NOTICE: [db_dist_hypertable_3]: - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial' -NOTICE: [db_dist_hypertable_3]: -column_name|column_default ------------+-------------- -time | -device | -id1 | -id2 | -id3 | -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Ensure sequences were created on the AN only -INSERT INTO disttable_serial VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT currval('disttable_serial_id1_seq'::regclass), - currval('disttable_serial_id2_seq'::regclass), - currval('disttable_serial_id3_seq'::regclass); - currval | currval | currval ----------+---------+--------- - 5 | 5 | 5 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT currval('disttable_serial_id1_seq'::regclass); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT currval('disttable_serial_id1_seq'::regclass) -ERROR: [db_dist_hypertable_1]: relation "disttable_serial_id1_seq" does not exist -\set ON_ERROR_STOP 1 --- Verify that the data is getting spread over multiple data nodes with the --- serial values being set correctly -SELECT * from disttable_serial ORDER BY id1; - time | device | id1 | id2 | id3 -------------------------------+--------+-----+-----+----- - Sun Jan 01 06:01:00 2017 PST | 1 | 1 | 1 | 1 - Sun Jan 01 09:11:00 2017 PST | 3 | 2 | 2 | 2 - Sun Jan 01 08:01:00 2017 PST | 1 | 3 | 3 | 3 - Mon Jan 02 08:01:00 2017 PST | 2 | 4 | 4 | 4 - Mon Jul 02 08:01:00 2018 PDT | 87 | 5 | 5 | 5 -(5 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * from disttable_serial ORDER BY id1; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_1]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 06:01:00 2017 PST| 1| 1| 1| 1 -Sun Jan 01 08:01:00 2017 PST| 1| 3| 3| 3 -Mon Jul 02 08:01:00 2018 PDT| 87| 5| 5| 5 -(3 rows) - - -NOTICE: [db_dist_hypertable_2]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_2]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Mon Jan 02 08:01:00 2017 PST| 2| 4| 4| 4 -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - SELECT * from disttable_serial ORDER BY id1 -NOTICE: [db_dist_hypertable_3]: -time |device|id1|id2|id3 -----------------------------+------+---+---+--- -Sun Jan 01 09:11:00 2017 PST| 3| 2| 2| 2 -(1 row) - - - remote_exec -------------- - -(1 row) - -DROP TABLE disttable_serial; --- Test insert batching case which will hit the limit of arguments for --- prepared statements (65k). --- --- Issue: #1702 --- distributed hypertable insert fails when # of columns are more than 65 --- --- Use default value -SET timescaledb.max_insert_batch_size TO 1000; -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int , - dummy6 int , - dummy7 int , - dummy8 int , - dummy9 int , - dummy10 int , - dummy11 int , - dummy12 int , - dummy13 int , - dummy14 int , - dummy15 int , - dummy16 int , - dummy17 int , - dummy18 int , - dummy19 int , - dummy20 int , - dummy21 int , - dummy22 int , - dummy23 int , - dummy24 int , - dummy25 int , - dummy26 int , - dummy27 int , - dummy28 int , - dummy29 int , - dummy30 int , - dummy31 int , - dummy32 int , - dummy33 int , - dummy34 int , - dummy35 int , - dummy36 int , - dummy37 int , - dummy38 int , - dummy39 int , - dummy40 int , - dummy41 int , - dummy42 int , - dummy43 int , - dummy44 int , - dummy45 int , - dummy46 int , - dummy47 int , - dummy48 int , - dummy49 int , - dummy50 int , - dummy51 int , - dummy52 int , - dummy53 int , - dummy54 int , - dummy55 int , - dummy56 int , - dummy57 int , - dummy58 int , - dummy59 int , - dummy60 int , - dummy61 int , - dummy62 int , - dummy63 int , - dummy64 int , - dummy65 int , - dummy66 int , - dummy67 int , - dummy68 int , - dummy69 int , - dummy70 int , - dummy71 int -); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (22,public,test_1702,t) -(1 row) - --- Original issue case --- --- Expect batch size to be lower than defined max_insert_batch_size --- -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; - QUERY PLAN ------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 910 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> ProjectSet - -> Result -(9 rows) - -INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; -SELECT count(*) from test_1702; - count -------- - 1500 -(1 row) - -DROP TABLE test_1702; --- --- Expect batch size to be similair to max_insert_batch_size --- -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int - ); -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: column type "character varying" used for "id" does not follow best practices -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (23,public,test_1702,t) -(1 row) - -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - QUERY PLAN ------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable test_1702 - -> Insert on test_1702 - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Result -(7 rows) - -DROP TABLE test_1702; --- --- Test that creating a hypertable with a space dimension and --- if_not_exists works as expected, that is, the second call does not --- generate an error (and does not crash). --- -CREATE TABLE whatever ( - timestamp TIMESTAMPTZ NOT NULL, - user_id INT NOT NULL, - data JSONB -); -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | t -(1 row) - --- Check the hypertable sequence before and after call to ensure that --- the hypertable sequence was not increased with the second call. -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -NOTICE: table "whatever" is already a hypertable, skipping - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 24 | public | whatever | f -(1 row) - -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - last_value ------------- - 24 -(1 row) - --- Test that creating a distributed hypertable from a table with data --- fails, and that migrate_data blocked. -CREATE TABLE dist_hypertable_1 ( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temp FLOAT -); -INSERT INTO dist_hypertable_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => FALSE); -WARNING: distributed hypertable is deprecated -ERROR: table "dist_hypertable_1" is not empty -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => TRUE); -WARNING: distributed hypertable is deprecated -ERROR: cannot migrate data for distributed hypertable -\set ON_ERROR_STOP 1 --- Test creating index with transaction per chunk on a distributed hypertable --- -DROP TABLE disttable; -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 25 | public | disttable | t -(1 row) - -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -\set ON_ERROR_STOP 0 -CREATE INDEX disttable_time_device_idx ON disttable (time, device) WITH (timescaledb.transaction_per_chunk); -ERROR: cannot use timescaledb.transaction_per_chunk with distributed hypertable -\set ON_ERROR_STOP 1 --- Test using system columns with distributed hypertable --- -CREATE TABLE dist_syscol(time timestamptz NOT NULL, color int, temp float); -SELECT * FROM create_distributed_hypertable('dist_syscol', 'time', 'color'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+-------------+--------- - 26 | public | dist_syscol | t -(1 row) - -INSERT INTO dist_syscol VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1); --- Return chunk table as a source -SET timescaledb.enable_per_data_node_queries = false; -SELECT tableoid::regclass, * FROM dist_syscol; - tableoid | time | color | temp ------------------------------------------------+------------------------------+-------+------ - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 06:01:00 2017 PST | 1 | 1.1 - _timescaledb_internal._dist_hyper_26_72_chunk | Wed Feb 01 08:01:00 2017 PST | 1 | 1.2 - _timescaledb_internal._dist_hyper_26_73_chunk | Fri Feb 02 08:01:00 2018 PST | 2 | 1.3 - _timescaledb_internal._dist_hyper_26_74_chunk | Fri Feb 01 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_74_chunk | Sat Feb 02 09:11:00 2019 PST | 3 | 2.1 - _timescaledb_internal._dist_hyper_26_75_chunk | Sat Feb 02 10:01:00 2019 PST | 5 | 1.2 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 08:21:00 2019 PST | 4 | 6.6 - _timescaledb_internal._dist_hyper_26_75_chunk | Mon Feb 04 10:11:00 2019 PST | 7 | 7.4 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 02:11:00 2019 PST | 5 | 1.8 - _timescaledb_internal._dist_hyper_26_75_chunk | Wed Feb 06 01:13:00 2019 PST | 7 | 7.9 - _timescaledb_internal._dist_hyper_26_76_chunk | Sun Feb 03 11:11:00 2019 PST | 6 | 3.5 - _timescaledb_internal._dist_hyper_26_76_chunk | Mon Feb 04 12:11:00 2019 PST | 8 | 2.1 - _timescaledb_internal._dist_hyper_26_76_chunk | Tue Feb 05 13:31:00 2019 PST | 8 | 6.3 - _timescaledb_internal._dist_hyper_26_77_chunk | Wed Feb 06 19:24:00 2019 PST | 9 | 5.9 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 18:44:00 2019 PST | 5 | 9.7 - _timescaledb_internal._dist_hyper_26_78_chunk | Thu Feb 07 09:33:00 2019 PST | 7 | 9.5 - _timescaledb_internal._dist_hyper_26_78_chunk | Fri Feb 08 18:14:00 2019 PST | 4 | 8.2 - _timescaledb_internal._dist_hyper_26_79_chunk | Thu Feb 07 20:24:00 2019 PST | 6 | - _timescaledb_internal._dist_hyper_26_79_chunk | Fri Feb 08 08:54:00 2019 PST | 1 | 7.3 - _timescaledb_internal._dist_hyper_26_79_chunk | Sat Feb 09 19:23:00 2019 PST | 8 | 9.1 -(20 rows) - --- Produce an error -SET timescaledb.enable_per_data_node_queries = true; -\set ON_ERROR_STOP 0 -SELECT tableoid::regclass, * FROM dist_syscol; -ERROR: system columns are not accessible on distributed hypertables with current settings -\set ON_ERROR_STOP 1 ------------------------ --- Test DataNodeCopy -- ------------------------ -SET timescaledb.enable_distributed_insert_with_copy=true; -DROP TABLE disttable; --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with DataNodeCopy -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 27 | public | disttable | t -(1 row) - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -CREATE TYPE highlow AS (high int, low int); -CALL distributed_exec($$ CREATE TYPE highlow AS (high int, low int) $$); -ALTER TABLE datatable ADD COLUMN minmaxes highlow[]; -INSERT INTO datatable (id, time, device, temp_c, minmaxes) VALUES - (1, '2017-01-01 06:01', 1, 1.2, ARRAY[(1,2)::highlow]), - (2, '2017-01-01 09:11', 3, 4.3, ARRAY[(2,3)::highlow]), - (3, '2017-01-01 08:01', 1, 7.3, ARRAY[(4,5)::highlow]), - (4, '2017-01-02 08:01', 2, 0.23, ARRAY[(6,7)::highlow]), - (5, '2018-07-02 08:01', 87, 0.0, ARRAY[(8,9)::highlow]), - (6, '2018-07-01 06:01', 13, 3.1, ARRAY[(10,11)::highlow]), - (7, '2018-07-01 09:11', 90, 10303.12, ARRAY[(12,13)::highlow]), - (8, '2018-07-01 08:01', 29, 64, ARRAY[(14,15)::highlow]); --- Show that DataNodeCopy is used instead of DataNodeDispatch. Should --- default to FORMAT binary in the remote SQL. Add RETURNING to show --- that it works. -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Remote SQL: COPY public.disttable (id, "time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(13 rows) - --- Perform the actual insert -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - --- Show that the data was added: -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c -----+------------------------------+--------+---------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 -(8 rows) - -SELECT count(*) FROM disttable; - count -------- - 8 -(1 row) - --- Add an array of a composite type to check that DataNodeCopy --- switches to text format if we use a table with an array of a custom --- type. There should be no "FORMAT binary" in the remote explain. -ALTER TABLE disttable ADD COLUMN minmaxes highlow[]; -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..24.55 rows=970 width=56) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..24.55 rows=970 width=56) - -> Custom Scan (DataNodeCopy) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - Remote SQL: COPY public.disttable (id, "time", device, temp_c, minmaxes) FROM STDIN - -> Custom Scan (ChunkDispatch) (cost=0.00..24.55 rows=970 width=56) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes - -> Seq Scan on public.datatable (cost=0.00..24.55 rows=970 width=56) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c, datatable.minmaxes -(11 rows) - -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; --- Should have double amount of rows compared to before and half of --- them values in the new column. Note, must use TEXT format on the --- connection to make query work with custom type array. -SET timescaledb.enable_connection_binary_data=false; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -SELECT count(*) FROM disttable; - count -------- - 16 -(1 row) - --- Binary format should lead to data incompatibility in PG 13 and earlier, --- because the highlow data type has different oids on data and access nodes. --- Use this to test the deserialization error reporting. Newer PG version --- ignore this oid mismatch for non-builtin types. -SET timescaledb.enable_connection_binary_data=true; -\set ON_ERROR_STOP 0 -SET timescaledb.remote_data_fetcher = 'copy'; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -SET timescaledb.remote_data_fetcher = 'cursor'; -SELECT * FROM disttable ORDER BY 1; - id | time | device | temp_c | minmaxes -----+------------------------------+--------+----------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | - 9 | Sun Jan 01 06:01:00 2017 PST | 1 | 1.2 | {"(1,2)"} - 10 | Sun Jan 01 09:11:00 2017 PST | 3 | 4.3 | {"(2,3)"} - 11 | Sun Jan 01 08:01:00 2017 PST | 1 | 7.3 | {"(4,5)"} - 12 | Mon Jan 02 08:01:00 2017 PST | 2 | 0.23 | {"(6,7)"} - 13 | Mon Jul 02 08:01:00 2018 PDT | 87 | 0 | {"(8,9)"} - 14 | Sun Jul 01 06:01:00 2018 PDT | 13 | 3.1 | {"(10,11)"} - 15 | Sun Jul 01 09:11:00 2018 PDT | 90 | 10303.12 | {"(12,13)"} - 16 | Sun Jul 01 08:01:00 2018 PDT | 29 | 64 | {"(14,15)"} -(16 rows) - -\set ON_ERROR_STOP 1 -RESET timescaledb.remote_data_fetcher; --- Show that DataNodeCopy is NOT used when source hypertable and target hypertable --- of the SELECT are both distributed. Try subselects with LIMIT, RETURNING and --- different distributed hypertable as source -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; - QUERY PLAN ------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(13 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable LIMIT 1; - QUERY PLAN ------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Subquery Scan on "*SELECT*" - -> Limit - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(13 rows) - -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) - Insert on distributed hypertable disttable - -> Insert on disttable - -> Custom Scan (DataNodeDispatch) - Batch size: 1000 - -> Custom Scan (ChunkDispatch) - -> Append - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_2 - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_3 - -> Result - -> Custom Scan (DataNodeScan) on disttable disttable_4 -(13 rows) - -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; -INSERT INTO disttable (time, device, temp_c) -SELECT * FROM hyper_estimate LIMIT 2; -SELECT count(*) FROM disttable; - count -------- - 34 -(1 row) - --- REMOVE a column on data nodes to check how errors are handled: -CALL distributed_exec($$ ALTER TABLE disttable DROP COLUMN minmaxes $$); -\set ON_ERROR_STOP 0 -INSERT INTO disttable SELECT * FROM datatable; -ERROR: [db_dist_hypertable_1]: column "minmaxes" of relation "disttable" does not exist -\set ON_ERROR_STOP 1 -DROP TABLE disttable; --- Create a new table access method by reusing heap handler -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_2]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler -NOTICE: [db_dist_hypertable_3]: -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler - remote_exec -------------- - -(1 row) - --- Create distributed hypertable using non-default access method -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp_c float, temp_f float GENERATED ALWAYS AS (temp_c * 9 / 5 + 32) STORED) USING test_am; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 28 | public | disttable | t -(1 row) - --- Make sure that distributed hypertable created on data nodes is --- using the correct table access method -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_hypertable_1]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_1]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_2]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_2]: -hypertable_amname ------------------ -test_am -(1 row) - - -NOTICE: [db_dist_hypertable_3]: - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid -NOTICE: [db_dist_hypertable_3]: -hypertable_amname ------------------ -test_am -(1 row) - - - remote_exec -------------- - -(1 row) - --- Check that basic operations are working as expected -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, -10.0), - ('2017-01-01 09:11', 3, -5.0), - ('2017-01-01 08:01', 1, 1.0), - ('2017-01-02 08:01', 2, 5.0), - ('2018-07-02 08:01', 87, 10.0), - ('2018-07-01 06:01', 13, 15.0), - ('2018-07-01 09:11', 90, 20.0), - ('2018-07-01 08:01', 29, 24.0); -SELECT * FROM disttable ORDER BY time; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Sun Jan 01 06:01:00 2017 PST | 1 | -10 | 14 - Sun Jan 01 08:01:00 2017 PST | 1 | 1 | 33.8 - Sun Jan 01 09:11:00 2017 PST | 3 | -5 | 23 - Mon Jan 02 08:01:00 2017 PST | 2 | 5 | 41 - Sun Jul 01 06:01:00 2018 PDT | 13 | 15 | 59 - Sun Jul 01 08:01:00 2018 PDT | 29 | 24 | 75.2 - Sun Jul 01 09:11:00 2018 PDT | 90 | 20 | 68 - Mon Jul 02 08:01:00 2018 PDT | 87 | 10 | 50 -(8 rows) - --- Show that GENERATED columns work for INSERT with RETURNING clause --- (should use DataNodeCopy) -TRUNCATE disttable; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeCopy) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - Remote SQL: COPY public.disttable ("time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Tue Aug 01 06:01:00 2017 PDT'::timestamp with time zone, 1, '35'::double precision, NULL::double precision -(13 rows) - -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - --- Same values returned with SELECT: -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 35 | 95 -(1 row) - -UPDATE disttable SET temp_c=40.0 WHERE device=1; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 -(1 row) - --- Insert another value -INSERT INTO disttable VALUES ('2017-09-01 06:01', 2, 30.0); -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Tue Aug 01 06:01:00 2017 PDT | 1 | 40 | 104 - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(2 rows) - --- Delete a value based on the generated column -DELETE FROM disttable WHERE temp_f=104; -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 2 | 30 | 86 -(1 row) - --- Test also with DataNodeDispatch -TRUNCATE disttable; -SET timescaledb.enable_distributed_insert_with_copy=false; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - Insert on distributed hypertable public.disttable - Data nodes: db_dist_hypertable_1, db_dist_hypertable_2, db_dist_hypertable_3 - -> Insert on public.disttable (cost=0.00..0.01 rows=1 width=28) - Output: disttable."time", disttable.device, disttable.temp_c, disttable.temp_f - -> Custom Scan (DataNodeDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable("time", device, temp_c) VALUES ($1, $2, $3), ..., ($2998, $2999, $3000) RETURNING "time", device, temp_c, temp_f - -> Custom Scan (ChunkDispatch) (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision - -> Result (cost=0.00..0.01 rows=1 width=28) - Output: 'Fri Sep 01 06:01:00 2017 PDT'::timestamp with time zone, 5, '40'::double precision, NULL::double precision -(14 rows) - -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Generated columns with SELECT -SELECT * FROM disttable ORDER BY 1; - time | device | temp_c | temp_f -------------------------------+--------+--------+-------- - Fri Sep 01 06:01:00 2017 PDT | 5 | 40 | 104 -(1 row) - --- Check distributed hypertable within procedure properly drops remote tables --- --- #3663 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (29,public,test,t) -(1 row) - -CREATE PROCEDURE test_drop() LANGUAGE PLPGSQL AS $$ -BEGIN - DROP TABLE test; -END -$$; -CALL test_drop(); -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (30,public,test,t) -(1 row) - -DROP TABLE test; --- Test that stable functions are calculated on the access node. --- --- As a stable function to test, use the timestamp -> timestamptz conversion --- that is stable because it uses the current timezone. --- We have to be careful about `timestamp < timestamptz` comparison. From postgres --- docs: --- When comparing a timestamp without time zone to a timestamp with time zone, --- the former value is assumed to be given in the time zone specified by the --- TimeZone configuration parameter, and is rotated to UTC for comparison to --- the latter value (which is already in UTC internally). --- We don't want this to happen on data node, so we cast the filter value to --- timestamp, and check that this cast happens on the access node and uses the --- current timezone. -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -CREATE TABLE test_tz (time timestamp, v int); -SELECT create_distributed_hypertable('test_tz','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (31,public,test_tz,t) -(1 row) - -INSERT INTO test_tz VALUES ('2018-01-02 12:00:00', 2), ('2018-01-02 11:00:00', 1), - ('2018-01-02 13:00:00', 3), ('2018-01-02 14:00:00', 4); -SET TIME ZONE 'Etc/GMT'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Normal WHERE clause on baserel -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 14:00:00 2018 | 4 -(2 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- Also test different code paths used with aggregation pushdown. -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 2 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(27 rows) - --- TODO: test HAVING here and in the later now() tests as well. --- Change the timezone and check that the conversion is applied correctly. -SET TIME ZONE 'Etc/GMT+1'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - timestamp --------------------------- - Tue Jan 02 11:00:00 2018 -(1 row) - -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - time | v ---------------------------+--- - Tue Jan 02 13:00:00 2018 | 3 - Tue Jan 02 12:00:00 2018 | 2 - Tue Jan 02 14:00:00 2018 | 4 -(3 rows) - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(30 rows) - -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - count -------- - 3 -(1 row) - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Aggregate - Output: count(*) - -> Custom Scan (AsyncAppend) - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Index Only Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT NULL FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 11:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Result - Output: NULL::text - -> Append - -> Index Only Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_96_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_96_chunk - Index Cond: (_dist_hyper_31_96_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -> Index Only Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 11:00:00'::timestamp without time zone) - -(29 rows) - --- Conversion to timestamptz cannot be evaluated at the access node, because the --- argument is a column reference. -SELECT count(*) FROM test_tz WHERE time::timestamptz > now(); - count -------- - 0 -(1 row) - --- According to our docs, JIT is not recommended for use on access node in --- multi-node environment. Turn it off so that it doesn't ruin EXPLAIN for the --- next query. -SET jit = 0; --- Test that operators are evaluated as well. Comparison of timestamp with --- timestamptz is a stable operator, and comparison of two timestamps is an --- immutable operator. This also test that immutable functions using these --- operators as arguments are evaluated. -EXPLAIN (verbose, costs off) -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT * FROM test_tz, dummy -WHERE time > x - + (x = x)::int -- stable - * (x = '2018-01-02 11:00:00'::timestamp)::int -- immutable - * INTERVAL '1 hour'; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v, (('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone) - -> Append - -> Result - Output: test_tz_1."time", test_tz_1.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Index Scan using _dist_hyper_31_97_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Index Cond: (_dist_hyper_31_97_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - - -> Result - Output: test_tz_2."time", test_tz_2.v, ('Tue Jan 02 11:00:00 2018 -01'::timestamp with time zone)::timestamp without time zone - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time" > '2018-01-02 12:00:00'::timestamp without time zone)) - Remote EXPLAIN: - Append - -> Index Scan using _dist_hyper_31_95_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Index Cond: (_dist_hyper_31_95_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -> Index Scan using _dist_hyper_31_98_chunk_test_tz_time_idx on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Index Cond: (_dist_hyper_31_98_chunk."time" > '2018-01-02 12:00:00'::timestamp without time zone) - -(31 rows) - --- Reference value for the above test. -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT x + (x = x)::int * (x = '2018-01-02 11:00:00'::timestamp)::int * INTERVAL '1 hour' -FROM dummy; - ?column? --------------------------- - Tue Jan 02 12:00:00 2018 -(1 row) - --- Exercise some more stable timestamp-related functions. -EXPLAIN (COSTS OFF, VERBOSE) -SELECT * FROM test_tz WHERE date_trunc('month', time) > date_in('2021-01-01') - AND time::time > '00:00:00'::time - + (INTERVAL '1 hour') * date_part('hour', INTERVAL '1 hour'); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: test_tz."time", test_tz.v - -> Append - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_1 - Output: test_tz_1."time", test_tz_1.v - Data node: db_dist_hypertable_1 - Chunks: _dist_hyper_31_97_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Seq Scan on _timescaledb_internal._dist_hyper_31_97_chunk - Output: _dist_hyper_31_97_chunk."time", _dist_hyper_31_97_chunk.v - Filter: (((_dist_hyper_31_97_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_97_chunk."time") > '2021-01-01'::date)) - - -> Custom Scan (DataNodeScan) on public.test_tz test_tz_2 - Output: test_tz_2."time", test_tz_2.v - Data node: db_dist_hypertable_2 - Chunks: _dist_hyper_31_95_chunk, _dist_hyper_31_96_chunk, _dist_hyper_31_98_chunk - Remote SQL: SELECT "time", v FROM public.test_tz WHERE _timescaledb_functions.chunks_in(public.test_tz.*, ARRAY[43, 44, 45]) AND (("time"::time without time zone > '01:00:00'::time without time zone)) AND ((date_trunc('month'::text, "time") > '2021-01-01'::date)) - Remote EXPLAIN: - Append - -> Seq Scan on _timescaledb_internal._dist_hyper_31_95_chunk - Output: _dist_hyper_31_95_chunk."time", _dist_hyper_31_95_chunk.v - Filter: (((_dist_hyper_31_95_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_95_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_96_chunk - Output: _dist_hyper_31_96_chunk."time", _dist_hyper_31_96_chunk.v - Filter: (((_dist_hyper_31_96_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_96_chunk."time") > '2021-01-01'::date)) - -> Seq Scan on _timescaledb_internal._dist_hyper_31_98_chunk - Output: _dist_hyper_31_98_chunk."time", _dist_hyper_31_98_chunk.v - Filter: (((_dist_hyper_31_98_chunk."time")::time without time zone > '01:00:00'::time without time zone) AND (date_trunc('month'::text, _dist_hyper_31_98_chunk."time") > '2021-01-01'::date)) - -(30 rows) - --- Check that the test function for partly overriding now() works. It's very --- hacky and only has effect when we estimate some costs or evaluate sTABLE --- functions in quals on access node, and has no effect in other cases. --- Consider deleting it altogether. -SELECT test.tsl_override_current_timestamptz('2018-01-02 12:00:00 +00'::timestamptz); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -SELECT count(*) FROM test_tz WHERE time > now(); - count -------- - 3 -(1 row) - -SELECT test.tsl_override_current_timestamptz(null); - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - -RESET TIME ZONE; -DROP TABLE test_tz; --- Check that now() is evaluated on the access node. Also check that it is evaluated --- anew on every execution of a prepared statement. -CREATE TABLE test_now (time timestamp, v int); -SELECT create_distributed_hypertable('test_now','time', - chunk_time_interval => interval '1 hour'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (32,public,test_now,t) -(1 row) - -PREPARE test_query as -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; -; -BEGIN; -- to fix the value of now(); -INSERT INTO test_now VALUES - (now(), 1), (now() + INTERVAL '1 hour', 1), - (now() + INTERVAL '2 hour', 2 ), (now() + INTERVAL '3 hour', 3); -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 1 | 0 | 3 -(1 row) - --- Also test different code paths used with aggregation pushdown. --- We can't run EXPLAIN here, because now() is different every time. But the --- strict equality should be enough to detect if now() is being erroneously --- evaluated on data node, where it will differ from time to time. -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 1 -(1 row) - -COMMIT; --- now() will be different in a new transaction. -BEGIN; -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -EXECUTE test_query; - count | count | count --------+-------+------- - 0 | 1 | 3 -(1 row) - -SELECT count(*) FROM test_now WHERE time = now(); - count -------- - 0 -(1 row) - -COMMIT; -DROP TABLE test_now; -DEALLOCATE test_query; --- Check enabling distributed compression within a --- procedure/function works --- --- #3705 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (33,public,test,t) -(1 row) - -CREATE PROCEDURE test_set_compression() LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); -END -$$; -CALL test_set_compression(); -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_33_103_chunk -(1 row) - -DROP TABLE test; -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices -NOTICE: adding not-null constraint to column "time" - create_distributed_hypertable -------------------------------- - (34,public,test,t) -(1 row) - -CREATE FUNCTION test_set_compression_func() RETURNS BOOL LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); - RETURN TRUE; -END -$$; -SELECT test_set_compression_func(); - test_set_compression_func ---------------------------- - t -(1 row) - -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); - compress_chunk ------------------------------------------------- - _timescaledb_internal._dist_hyper_34_104_chunk -(1 row) - -DROP TABLE test; --- Fix ALTER SET/DROP NULL constraint on distributed hypertable --- --- #3860 --- -CREATE TABLE test (time timestamp NOT NULL, my_column int NOT NULL); -SELECT create_distributed_hypertable('test','time'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (35,public,test,t) -(1 row) - -\set ON_ERROR_STOP 0 -INSERT INTO test VALUES (now(), NULL); -ERROR: [db_dist_hypertable_3]: null value in column "my_column" of relation "_dist_hyper_35_105_chunk" violates not-null constraint -\set ON_ERROR_STOP 1 -ALTER TABLE test ALTER COLUMN my_column DROP NOT NULL; -INSERT INTO test VALUES (now(), NULL); -\set ON_ERROR_STOP 0 -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -ERROR: [db_dist_hypertable_3]: column "my_column" of relation "_dist_hyper_35_106_chunk" contains null values -\set ON_ERROR_STOP 1 -DELETE FROM test; -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -DROP TABLE test; --- Test insert into distributed hypertable with pruned chunks -CREATE TABLE pruned_chunks_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_1', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_1 -(1 row) - -INSERT INTO pruned_chunks_1 VALUES ('2020-12-09',1,32.2); -CREATE TABLE pruned_chunks_2(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); --- Convert the table to a distributed hypertable -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_2', 'time', 'sensor_id'); -WARNING: distributed hypertable is deprecated - table_name ------------------ - pruned_chunks_2 -(1 row) - -insert into pruned_chunks_2 select * from pruned_chunks_1; -insert into pruned_chunks_2 select * from pruned_chunks_1 WHERE time > '2022-01-01'; --- TEST freeze_chunk api. does not work for distributed chunks -SELECT chunk_schema || '.' || chunk_name as "CHNAME" -FROM timescaledb_information.chunks -WHERE hypertable_name = 'pruned_chunks_1' -ORDER BY chunk_name LIMIT 1 -\gset -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( :'CHNAME'); -ERROR: operation not supported on distributed chunk or foreign table "_dist_hyper_36_107_chunk" -\set ON_ERROR_STOP 1 ---TEST freeze_chunk api for regular hypertables. Works only for >= PG14 -CREATE TABLE freeze_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_hypertable('freeze_1', 'time'); - table_name ------------- - freeze_1 -(1 row) - -INSERT INTO freeze_1 VALUES ('2020-12-09',1,32.2); -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( ch) FROM ( select show_chunks('freeze_1') ch ) q; - freeze_chunk --------------- - t -(1 row) - -\set ON_ERROR_STOP 1 -DROP TABLE pruned_chunks_1; -DROP TABLE pruned_chunks_2; --- Cleanup -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_move_chunk-13.out b/tsl/test/expected/dist_move_chunk-13.out deleted file mode 100644 index f3c5ccea855..00000000000 --- a/tsl/test/expected/dist_move_chunk-13.out +++ /dev/null @@ -1,630 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_move_chunk_1 | db_dist_move_chunk_1 | t | t | t - db_dist_move_chunk_2 | db_dist_move_chunk_2 | t | t | t - db_dist_move_chunk_3 | db_dist_move_chunk_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (1,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_1]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure data node name is provided and has proper type -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> null, destination_node => :'DATA_NODE_2'); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => null); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => 2); -ERROR: procedure timescaledb_experimental.copy_chunk(chunk => unknown, source_node => unknown, destination_node => integer) does not exist at character 6 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node => :'DATA_NODE_1'); -ERROR: invalid source or destination node -\set ON_ERROR_STOP 1 --- ensure functions can't be run in read only mode -SET default_transaction_read_only TO on; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute move_chunk() in a read-only transaction -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute copy_chunk() in a read-only transaction -\set ON_ERROR_STOP 1 -SET default_transaction_read_only TO off; --- ensure functions can't be run in an active multi-statement transaction -\set ON_ERROR_STOP 0 -BEGIN; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: move_chunk cannot run inside a transaction block -ROLLBACK; -BEGIN; -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: copy_chunk cannot run inside a transaction block -ROLLBACK; -\set ON_ERROR_STOP 1 --- must be superuser to copy/move chunks -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: must be superuser, replication role, or hypertable owner to copy/move chunk to data node -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_1; --- can't run copy/move chunk on a data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- ensure that hypertable chunks are distributed -CREATE TABLE nondist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_hypertable('nondist_test', 'time', 'device', 3); -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_hypertable ---------------------------- - (2,public,nondist_test,t) -(1 row) - -INSERT INTO nondist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('nondist_test'); - show_chunks ----------------------------------------- - _timescaledb_internal._hyper_2_5_chunk - _timescaledb_internal._hyper_2_6_chunk - _timescaledb_internal._hyper_2_7_chunk - _timescaledb_internal._hyper_2_8_chunk -(4 rows) - -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -\set ON_ERROR_STOP 1 --- ensure that chunk exists on a source data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_2_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_2_chunk" does not exist on source data node "db_dist_move_chunk_1" -\set ON_ERROR_STOP 1 --- do actualy copy -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_2]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_2]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure that chunk exists on a destination data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_1_chunk" already exists on destination data node "db_dist_move_chunk_2" -\set ON_ERROR_STOP 1 --- now try to move the same chunk from data node 2 to 3 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_3]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_3]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Check that they can be called from inside a procedure without --- generating warnings or error messages (#3495). -CREATE OR REPLACE PROCEDURE copy_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.copy_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -CREATE OR REPLACE PROCEDURE move_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.move_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_2} | {db_dist_move_chunk_1,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3} | {db_dist_move_chunk_1,db_dist_move_chunk_2} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -CALL copy_wrapper('_timescaledb_internal._dist_hyper_1_3_chunk', :'DATA_NODE_3', :'DATA_NODE_2'); -CALL move_wrapper('_timescaledb_internal._dist_hyper_1_2_chunk', :'DATA_NODE_2', :'DATA_NODE_1'); -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3,db_dist_move_chunk_2} | {db_dist_move_chunk_1} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -DROP PROCEDURE copy_wrapper; -DROP PROCEDURE move_wrapper; -DROP TABLE dist_test; --- Test copy/move compressed chunk --- --- Create a compressed hypertable -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (3,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -ALTER TABLE dist_test SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Integrity check (see below) -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Get a list of chunks -SELECT * from show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_1} -(4 rows) - --- Compress a chunk -SELECT compress_chunk('_timescaledb_internal._dist_hyper_3_12_chunk'); - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_12_chunk -(1 row) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk name on the source data node and show its content -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk stat -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 -(1 row) - --- Move compressed chunk from data node 1 to data node 2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT count(*) FROM _timescaledb_catalog.chunk_copy_operation; - count -------- - 5 -(1 row) - --- Make sure same compressed chunk hash been created on the destination data node -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; --- Chunk created on data node has different id but the same name, make sure --- compressed_chunk_id is correctly set -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - --- Try to query hypertable member with compressed chunk -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Ensure that compressed chunk stats match stats from the source data node -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 -(1 row) - --- Ensure moved chunks are no longer present on the source data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name ------------- -(0 rows) - -\set ON_ERROR_STOP 0 -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -ERROR: relation "_timescaledb_internal.compress_hyper_3_6_chunk" does not exist at character 15 -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; -ERROR: relation "_timescaledb_internal._dist_hyper_3_12_chunk" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Make sure chunk has been properly moved from AN -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_2} -(4 rows) - --- Query distributed hypertable again to query newly moved chunk, make --- sure result has not changed -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Test operation_id name validation -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(operation_id => ' move chunk id ', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name " move chunk id " is not valid -CALL timescaledb_experimental.move_chunk(operation_id => 'ChUnK_MoVe_Op', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "ChUnK_MoVe_Op" is not valid -CALL timescaledb_experimental.move_chunk(operation_id => '_ID123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "_ID123" is not valid -\set ON_ERROR_STOP 1 --- Now copy chunk from data node 2 to data node 3 -CALL timescaledb_experimental.move_chunk(operation_id => 'id123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; --- Validate chunk on data node 3 -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 8192 | 16384 | 8192 | 32768 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- _dist_hyper_3_12_chunk should be moved in data node 3 now -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_3} -(4 rows) - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_move_chunk-14.out b/tsl/test/expected/dist_move_chunk-14.out deleted file mode 100644 index 8f1bf044552..00000000000 --- a/tsl/test/expected/dist_move_chunk-14.out +++ /dev/null @@ -1,630 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_move_chunk_1 | db_dist_move_chunk_1 | t | t | t - db_dist_move_chunk_2 | db_dist_move_chunk_2 | t | t | t - db_dist_move_chunk_3 | db_dist_move_chunk_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (1,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_1]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure data node name is provided and has proper type -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> null, destination_node => :'DATA_NODE_2'); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => null); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => 2); -ERROR: procedure timescaledb_experimental.copy_chunk(chunk => unknown, source_node => unknown, destination_node => integer) does not exist at character 6 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node => :'DATA_NODE_1'); -ERROR: invalid source or destination node -\set ON_ERROR_STOP 1 --- ensure functions can't be run in read only mode -SET default_transaction_read_only TO on; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute move_chunk() in a read-only transaction -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute copy_chunk() in a read-only transaction -\set ON_ERROR_STOP 1 -SET default_transaction_read_only TO off; --- ensure functions can't be run in an active multi-statement transaction -\set ON_ERROR_STOP 0 -BEGIN; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: move_chunk cannot run inside a transaction block -ROLLBACK; -BEGIN; -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: copy_chunk cannot run inside a transaction block -ROLLBACK; -\set ON_ERROR_STOP 1 --- must be superuser to copy/move chunks -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: must be superuser, replication role, or hypertable owner to copy/move chunk to data node -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_1; --- can't run copy/move chunk on a data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- ensure that hypertable chunks are distributed -CREATE TABLE nondist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_hypertable('nondist_test', 'time', 'device', 3); -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_hypertable ---------------------------- - (2,public,nondist_test,t) -(1 row) - -INSERT INTO nondist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('nondist_test'); - show_chunks ----------------------------------------- - _timescaledb_internal._hyper_2_5_chunk - _timescaledb_internal._hyper_2_6_chunk - _timescaledb_internal._hyper_2_7_chunk - _timescaledb_internal._hyper_2_8_chunk -(4 rows) - -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -\set ON_ERROR_STOP 1 --- ensure that chunk exists on a source data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_2_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_2_chunk" does not exist on source data node "db_dist_move_chunk_1" -\set ON_ERROR_STOP 1 --- do actualy copy -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_2]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_2]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure that chunk exists on a destination data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_1_chunk" already exists on destination data node "db_dist_move_chunk_2" -\set ON_ERROR_STOP 1 --- now try to move the same chunk from data node 2 to 3 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_3]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_3]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Check that they can be called from inside a procedure without --- generating warnings or error messages (#3495). -CREATE OR REPLACE PROCEDURE copy_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.copy_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -CREATE OR REPLACE PROCEDURE move_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.move_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_2} | {db_dist_move_chunk_1,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3} | {db_dist_move_chunk_1,db_dist_move_chunk_2} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -CALL copy_wrapper('_timescaledb_internal._dist_hyper_1_3_chunk', :'DATA_NODE_3', :'DATA_NODE_2'); -CALL move_wrapper('_timescaledb_internal._dist_hyper_1_2_chunk', :'DATA_NODE_2', :'DATA_NODE_1'); -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3,db_dist_move_chunk_2} | {db_dist_move_chunk_1} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -DROP PROCEDURE copy_wrapper; -DROP PROCEDURE move_wrapper; -DROP TABLE dist_test; --- Test copy/move compressed chunk --- --- Create a compressed hypertable -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (3,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -ALTER TABLE dist_test SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Integrity check (see below) -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Get a list of chunks -SELECT * from show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_1} -(4 rows) - --- Compress a chunk -SELECT compress_chunk('_timescaledb_internal._dist_hyper_3_12_chunk'); - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_12_chunk -(1 row) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk name on the source data node and show its content -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk stat -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - --- Move compressed chunk from data node 1 to data node 2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT count(*) FROM _timescaledb_catalog.chunk_copy_operation; - count -------- - 5 -(1 row) - --- Make sure same compressed chunk hash been created on the destination data node -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; --- Chunk created on data node has different id but the same name, make sure --- compressed_chunk_id is correctly set -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - --- Try to query hypertable member with compressed chunk -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Ensure that compressed chunk stats match stats from the source data node -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - --- Ensure moved chunks are no longer present on the source data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name ------------- -(0 rows) - -\set ON_ERROR_STOP 0 -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -ERROR: relation "_timescaledb_internal.compress_hyper_3_6_chunk" does not exist at character 15 -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; -ERROR: relation "_timescaledb_internal._dist_hyper_3_12_chunk" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Make sure chunk has been properly moved from AN -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_2} -(4 rows) - --- Query distributed hypertable again to query newly moved chunk, make --- sure result has not changed -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Test operation_id name validation -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(operation_id => ' move chunk id ', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name " move chunk id " is not valid -CALL timescaledb_experimental.move_chunk(operation_id => 'ChUnK_MoVe_Op', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "ChUnK_MoVe_Op" is not valid -CALL timescaledb_experimental.move_chunk(operation_id => '_ID123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "_ID123" is not valid -\set ON_ERROR_STOP 1 --- Now copy chunk from data node 2 to data node 3 -CALL timescaledb_experimental.move_chunk(operation_id => 'id123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; --- Validate chunk on data node 3 -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- _dist_hyper_3_12_chunk should be moved in data node 3 now -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_3} -(4 rows) - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_move_chunk-15.out b/tsl/test/expected/dist_move_chunk-15.out deleted file mode 100644 index 8f1bf044552..00000000000 --- a/tsl/test/expected/dist_move_chunk-15.out +++ /dev/null @@ -1,630 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -----------------------+----------------------+--------------+------------------+------------------- - db_dist_move_chunk_1 | db_dist_move_chunk_1 | t | t | t - db_dist_move_chunk_2 | db_dist_move_chunk_2 | t | t | t - db_dist_move_chunk_3 | db_dist_move_chunk_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (1,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); - show_chunks ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_1]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure data node name is provided and has proper type -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> null, destination_node => :'DATA_NODE_2'); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => null); -ERROR: invalid source or destination node -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => 2); -ERROR: procedure timescaledb_experimental.copy_chunk(chunk => unknown, source_node => unknown, destination_node => integer) does not exist at character 6 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node => :'DATA_NODE_1'); -ERROR: invalid source or destination node -\set ON_ERROR_STOP 1 --- ensure functions can't be run in read only mode -SET default_transaction_read_only TO on; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute move_chunk() in a read-only transaction -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: cannot execute copy_chunk() in a read-only transaction -\set ON_ERROR_STOP 1 -SET default_transaction_read_only TO off; --- ensure functions can't be run in an active multi-statement transaction -\set ON_ERROR_STOP 0 -BEGIN; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: move_chunk cannot run inside a transaction block -ROLLBACK; -BEGIN; -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: copy_chunk cannot run inside a transaction block -ROLLBACK; -\set ON_ERROR_STOP 1 --- must be superuser to copy/move chunks -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: must be superuser, replication role, or hypertable owner to copy/move chunk to data node -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_1; --- can't run copy/move chunk on a data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: function must be run on the access node only -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- ensure that hypertable chunks are distributed -CREATE TABLE nondist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_hypertable('nondist_test', 'time', 'device', 3); -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_hypertable ---------------------------- - (2,public,nondist_test,t) -(1 row) - -INSERT INTO nondist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('nondist_test'); - show_chunks ----------------------------------------- - _timescaledb_internal._hyper_2_5_chunk - _timescaledb_internal._hyper_2_6_chunk - _timescaledb_internal._hyper_2_7_chunk - _timescaledb_internal._hyper_2_8_chunk -(4 rows) - -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: "_hyper_2_5_chunk" is not a valid remote chunk -\set ON_ERROR_STOP 1 --- ensure that chunk exists on a source data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_2_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_2_chunk" does not exist on source data node "db_dist_move_chunk_1" -\set ON_ERROR_STOP 1 --- do actualy copy -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_2]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_2]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - --- ensure that chunk exists on a destination data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ERROR: chunk "_dist_hyper_1_1_chunk" already exists on destination data node "db_dist_move_chunk_2" -\set ON_ERROR_STOP 1 --- now try to move the same chunk from data node 2 to 3 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_1_chunk -(2 rows) - - - remote_exec -------------- - -(1 row) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_3]: SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk -NOTICE: [db_dist_move_chunk_3]: -sum ---- -406 -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Check that they can be called from inside a procedure without --- generating warnings or error messages (#3495). -CREATE OR REPLACE PROCEDURE copy_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.copy_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -CREATE OR REPLACE PROCEDURE move_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.move_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_2} | {db_dist_move_chunk_1,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3} | {db_dist_move_chunk_1,db_dist_move_chunk_2} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -CALL copy_wrapper('_timescaledb_internal._dist_hyper_1_3_chunk', :'DATA_NODE_3', :'DATA_NODE_2'); -CALL move_wrapper('_timescaledb_internal._dist_hyper_1_2_chunk', :'DATA_NODE_2', :'DATA_NODE_1'); -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - chunk_name | replica_nodes | non_replica_nodes ------------------------+---------------------------------------------+--------------------------------------------- - _dist_hyper_1_1_chunk | {db_dist_move_chunk_1,db_dist_move_chunk_3} | {db_dist_move_chunk_2} - _dist_hyper_1_2_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} - _dist_hyper_1_3_chunk | {db_dist_move_chunk_3,db_dist_move_chunk_2} | {db_dist_move_chunk_1} - _dist_hyper_1_4_chunk | {db_dist_move_chunk_1} | {db_dist_move_chunk_2,db_dist_move_chunk_3} -(4 rows) - -DROP PROCEDURE copy_wrapper; -DROP PROCEDURE move_wrapper; -DROP TABLE dist_test; --- Test copy/move compressed chunk --- --- Create a compressed hypertable -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "time" does not follow best practices - create_distributed_hypertable -------------------------------- - (3,public,dist_test,t) -(1 row) - -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -ALTER TABLE dist_test SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Integrity check (see below) -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Get a list of chunks -SELECT * from show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_1} -(4 rows) - --- Compress a chunk -SELECT compress_chunk('_timescaledb_internal._dist_hyper_3_12_chunk'); - compress_chunk ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_12_chunk -(1 row) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk name on the source data node and show its content -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Get compressed chunk stat -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - --- Move compressed chunk from data node 1 to data node 2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT count(*) FROM _timescaledb_catalog.chunk_copy_operation; - count -------- - 5 -(1 row) - --- Make sure same compressed chunk hash been created on the destination data node -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; --- Chunk created on data node has different id but the same name, make sure --- compressed_chunk_id is correctly set -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - --- Try to query hypertable member with compressed chunk -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - --- Ensure that compressed chunk stats match stats from the source data node -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - --- Ensure moved chunks are no longer present on the source data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name ------------- -(0 rows) - -\set ON_ERROR_STOP 0 -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -ERROR: relation "_timescaledb_internal.compress_hyper_3_6_chunk" does not exist at character 15 -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; -ERROR: relation "_timescaledb_internal._dist_hyper_3_12_chunk" does not exist at character 15 -\set ON_ERROR_STOP 1 --- Make sure chunk has been properly moved from AN -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM show_chunks('dist_test'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_3_9_chunk - _timescaledb_internal._dist_hyper_3_10_chunk - _timescaledb_internal._dist_hyper_3_11_chunk - _timescaledb_internal._dist_hyper_3_12_chunk -(4 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_move_chunk_1]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_1]: -show_chunks -------------------------------------------- -_timescaledb_internal._dist_hyper_3_9_chunk -(1 row) - - -NOTICE: [db_dist_move_chunk_2]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_10_chunk -_timescaledb_internal._dist_hyper_3_12_chunk -(2 rows) - - -NOTICE: [db_dist_move_chunk_3]: SELECT * from show_chunks('dist_test') -NOTICE: [db_dist_move_chunk_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_3_11_chunk -(1 row) - - - remote_exec -------------- - -(1 row) - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_2} -(4 rows) - --- Query distributed hypertable again to query newly moved chunk, make --- sure result has not changed -SELECT sum(device) FROM dist_test; - sum ------ - 846 -(1 row) - --- Test operation_id name validation -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(operation_id => ' move chunk id ', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name " move chunk id " is not valid -CALL timescaledb_experimental.move_chunk(operation_id => 'ChUnK_MoVe_Op', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "ChUnK_MoVe_Op" is not valid -CALL timescaledb_experimental.move_chunk(operation_id => '_ID123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -ERROR: operation_id name "_ID123" is not valid -\set ON_ERROR_STOP 1 --- Now copy chunk from data node 2 to data node 3 -CALL timescaledb_experimental.move_chunk(operation_id => 'id123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; --- Validate chunk on data node 3 -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - table_name --------------------------- - compress_hyper_3_6_chunk -(1 row) - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; - time | device | temp | _ts_meta_count | _ts_meta_sequence_num | _ts_meta_min_1 | _ts_meta_max_1 -----------------------------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-----------------------+--------------------------+-------------------------- - BAAAAgna9rUEAAACCdr2tQQAAAAAAQAAAAEAAAAAAAAADgAEE7XtaggA | 1 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 01:00:00 2018 | Thu Mar 08 01:00:00 2018 - BAAAAgnaICFgAAACCdogIWAAAAAAAQAAAAEAAAAAAAAADgAEE7RAQsAA | 10 | AwA/uZmZmZmZmgAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAEGAAAAAAAAAAIAAAABAAAAAQAAAAAAAAAGAAAAAAAAAD0AAAABPR/czMzMzMzN | 1 | 10 | Thu Mar 08 00:00:00 2018 | Thu Mar 08 00:00:00 2018 -(2 rows) - -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - time | device | temp ---------------------------+--------+------ - Thu Mar 08 00:00:00 2018 | 10 | 0.1 - Thu Mar 08 01:00:00 2018 | 1 | 0.1 -(2 rows) - -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | compression_status | uncompressed_heap_size | uncompressed_index_size | uncompressed_toast_size | uncompressed_total_size | compressed_heap_size | compressed_index_size | compressed_toast_size | compressed_total_size --------------------+-----------------+-----------------------+------------------------+--------------------+------------------------+-------------------------+-------------------------+-------------------------+----------------------+-----------------------+-----------------------+----------------------- - public | dist_test | _timescaledb_internal | _dist_hyper_3_12_chunk | Compressed | 8192 | 32768 | 0 | 40960 | 16384 | 16384 | 8192 | 40960 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- _dist_hyper_3_12_chunk should be moved in data node 3 now -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - ?column? | data_nodes -----------------------------------------------+------------------------ - _timescaledb_internal._dist_hyper_3_9_chunk | {db_dist_move_chunk_1} - _timescaledb_internal._dist_hyper_3_10_chunk | {db_dist_move_chunk_2} - _timescaledb_internal._dist_hyper_3_11_chunk | {db_dist_move_chunk_3} - _timescaledb_internal._dist_hyper_3_12_chunk | {db_dist_move_chunk_3} -(4 rows) - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_param.out b/tsl/test/expected/dist_param.out deleted file mode 100644 index e3ddaec1875..00000000000 --- a/tsl/test/expected/dist_param.out +++ /dev/null @@ -1,816 +0,0 @@ --- 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. --- Test parameterized data node scan. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DN_DBNAME_1 :TEST_DBNAME _1 --- pg_regress doesn't drop these databases for repeated invocation such as in --- the flaky check. -set client_min_messages to ERROR; -drop database if exists :"DN_DBNAME_1" with (force); -select 1 from add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); - ?column? ----------- - 1 -(1 row) - -grant usage on foreign server data_node_1 to public; -grant create on schema public to :ROLE_1; -set role :ROLE_1; -reset client_min_messages; -\set ON_ERROR_STOP 0 --- helper function: float -> pseudorandom float [0..1]. -create or replace function mix(x float4) returns float4 as $$ select ((hashfloat4(x) / (pow(2., 31) - 1) + 1) / 2)::float4 $$ language sql; --- distributed hypertable -create table metric_dist(ts timestamptz, id int, value float); -select create_distributed_hypertable('metric_dist', 'ts', 'id'); -WARNING: distributed hypertable is deprecated -WARNING: only one data node was assigned to the hypertable -NOTICE: adding not-null constraint to column "ts" - create_distributed_hypertable -------------------------------- - (1,public,metric_dist,t) -(1 row) - -insert into metric_dist - select '2022-02-02 02:02:02+03'::timestamptz + interval '1 year' * mix(x), - mix(x + 1.) * 20, - mix(x + 2.) * 50 - from generate_series(1, 1000000) x(x) -; -analyze metric_dist; -select count(*) from show_chunks('metric_dist'); - count -------- - 53 -(1 row) - --- dictionary -create table metric_name(id int, name text collate "C", - constraint metric_name_name unique (name), - constraint metric_name_id primary key (id)); -insert into metric_name values (1, 'cpu1'), (3, 'cpu3'), (7, 'cpu7'); -insert into metric_name select x, 'other' || x - from generate_series(1000, 10000) x -; -analyze metric_name; --- for predictable plans -set enable_hashagg to off; -set enable_material to off; -set enable_mergejoin to off; --- not present on PG 12 -\set ECHO errors --- Subquery + IN -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - -explain (costs off, verbose) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_dist.id, max(metric_dist.value), count(*) - Group Key: metric_dist.id - -> Sort - Output: metric_dist.id, metric_dist.value - Sort Key: metric_dist.id - -> Nested Loop - Output: metric_dist.id, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.value - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(17 rows) - --- Check that the GUC to disable these plans works. Our cost model is very --- heuristic and may be often wrong, so there needs to be a way to disable them. -set timescaledb.enable_parameterized_data_node_scan to false; -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - -explain (costs off, verbose) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_dist.id, max(metric_dist.value), count(*) - Group Key: metric_dist.id - -> Sort - Output: metric_dist.id, metric_dist.value - Sort Key: metric_dist.id - -> Hash Join - Output: metric_dist.id, metric_dist.value - Inner Unique: true - Hash Cond: (metric_dist.id = metric_name.id) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.value - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) ORDER BY id ASC NULLS LAST - -> Hash - Output: metric_name.id - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) -(21 rows) - -reset timescaledb.enable_parameterized_data_node_scan; --- All fetcher types with join -set timescaledb.remote_data_fetcher = 'copy'; -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; -ERROR: cannot use COPY fetcher because the plan is parameterized -set timescaledb.remote_data_fetcher = 'cursor'; -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - -set timescaledb.remote_data_fetcher = 'prepared'; -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - --- All fetcher types with initplan -set timescaledb.remote_data_fetcher = 'copy'; -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; -ERROR: cannot use COPY fetcher because the plan is parameterized -set timescaledb.remote_data_fetcher = 'cursor'; -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - -set timescaledb.remote_data_fetcher = 'prepared'; -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - id | max | count -----+------------------+------- - 1 | 49.9941974878311 | 4174 - 3 | 49.9958902597427 | 4119 - 7 | 49.9881327152252 | 4316 -(3 rows) - --- Should prefer prepared statement data fetcher for these queries. -set timescaledb.remote_data_fetcher = 'auto'; -explain (analyze, verbose, costs off, timing off, summary off) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=3 loops=1) - Output: metric_dist.id, max(metric_dist.value), count(*) - Group Key: metric_dist.id - -> Sort (actual rows=12609 loops=1) - Output: metric_dist.id, metric_dist.value - Sort Key: metric_dist.id - Sort Method: quicksort - -> Nested Loop (actual rows=12609 loops=1) - Output: metric_dist.id, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name (actual rows=3 loops=1) - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist (actual rows=4203 loops=3) - Output: metric_dist.id, metric_dist.value - Data node: data_node_1 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(19 rows) - --- Should reset the prepared cache mode after using the prepared statement fetcher. -call distributed_exec('create or replace procedure assert_auto_plan_cache_mode() as $$ begin assert (select setting from pg_settings where name = ''plan_cache_mode'') = ''auto''; end; $$ language plpgsql;'); -call distributed_exec('call assert_auto_plan_cache_mode();'); --- Shippable EC join -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - name | max | count -------+------------------+------- - cpu1 | 49.9941974878311 | 4174 - cpu3 | 49.9958902597427 | 4119 - cpu7 | 49.9881327152252 | 4316 -(3 rows) - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Nested Loop - Output: metric_name.name, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(14 rows) - --- Shipping still might make sense if the local table is outer. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist right join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Nested Loop - Output: metric_name.name, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(14 rows) - --- Shipping doesn't make sense if the distributed table is outer. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist -left join (select * from metric_name where name like 'cpu%') t using (id) -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Sort - Output: metric_name.name, metric_dist.value - Sort Key: metric_name.name COLLATE "C" - -> Hash Left Join - Output: metric_name.name, metric_dist.value - Inner Unique: true - Hash Cond: (metric_dist.id = metric_name.id) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) - -> Hash - Output: metric_name.name, metric_name.id - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.name, metric_name.id - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) -(21 rows) - --- Non-shippable EC join -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name on name = concat('cpu', metric_dist.id) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Sort - Output: metric_name.name, metric_dist.value - Sort Key: metric_name.name COLLATE "C" - -> Hash Join - Output: metric_name.name, metric_dist.value - Inner Unique: true - Hash Cond: ((concat('cpu', metric_dist.id))::text = metric_name.name) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) - -> Hash - Output: metric_name.name - -> Index Only Scan using metric_name_name on public.metric_name - Output: metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) -(21 rows) - --- Shippable non-EC join. The weird condition is to only use immutable functions --- that can be shipped to the remote node. `id::text` does CoerceViaIO which is --- not generally shippable. And `int4out` returns cstring, not text, that's why --- the `textin` is needed. -select name, max(value), count(*) -from metric_dist join metric_name - on texteq('cpu' || textin(int4out(metric_dist.id)), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - name | max | count -------+------------------+------- - cpu1 | 49.9941974878311 | 4174 - cpu3 | 49.9958902597427 | 4119 - cpu7 | 49.9881327152252 | 4316 -(3 rows) - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name - on texteq('cpu' || textin(int4out(metric_dist.id)), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Nested Loop - Output: metric_name.name, metric_dist.value - -> Index Only Scan using metric_name_name on public.metric_name - Output: metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (texteq(('cpu'::text || textin(int4out(id))), $1::text)) -(14 rows) - --- Non-shippable non-EC join. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name - on texteq(concat('cpu', textin(int4out(metric_dist.id))), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Nested Loop - Output: metric_name.name, metric_dist.value - Join Filter: texteq(concat('cpu', textin(int4out(metric_dist.id))), metric_name.name) - -> Index Only Scan using metric_name_name on public.metric_name - Output: metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) -(15 rows) - --- distinct on, order by, limit 1, with subquery -select distinct on (id) - id, ts, value -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, ts, value -limit 1 -; - id | ts | value -----+----------------------------------+------------------ - 1 | Tue Feb 01 15:03:56.048 2022 PST | 36.1639380455017 -(1 row) - -explain (costs off, verbose) -select distinct on (id) - id, ts, value -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, ts, value -limit 1 -; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: metric_dist.id, metric_dist.ts, metric_dist.value - -> Unique - Output: metric_dist.id, metric_dist.ts, metric_dist.value - -> Sort - Output: metric_dist.id, metric_dist.ts, metric_dist.value - Sort Key: metric_dist.id, metric_dist.ts, metric_dist.value - -> Nested Loop - Output: metric_dist.id, metric_dist.ts, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.ts, metric_dist.value - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT ts, id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(18 rows) - --- distinct on, order by, limit 1, with explicit join -select distinct on (name) - name, ts, value -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by name, ts, value -limit 1 -; - name | ts | value -------+----------------------------------+------------------ - cpu1 | Tue Feb 01 15:03:56.048 2022 PST | 36.1639380455017 -(1 row) - -explain (costs off, verbose) -select distinct on (name) - name, ts, value -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by name, ts, value -limit 1 -; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: metric_name.name, metric_dist.ts, metric_dist.value - -> Unique - Output: metric_name.name, metric_dist.ts, metric_dist.value - -> Sort - Output: metric_name.name, metric_dist.ts, metric_dist.value - Sort Key: metric_name.name COLLATE "C", metric_dist.ts, metric_dist.value - -> Nested Loop - Output: metric_name.name, metric_dist.ts, metric_dist.value - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.ts, metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT ts, id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(18 rows) - --- If there are a lot of rows chosen from the local table, the parameterized --- nested loop might download the entire dist table or even more than that (in --- case of not equi-join or duplicate join keys). --- Check that the parameterized plan is not chosen in this case. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist -join metric_name using (id) -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Sort - Output: metric_name.name, metric_dist.value - Sort Key: metric_name.name COLLATE "C" - -> Hash Join - Output: metric_name.name, metric_dist.value - Inner Unique: true - Hash Cond: (metric_dist.id = metric_name.id) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.value, metric_dist.id - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) - -> Hash - Output: metric_name.name, metric_name.id - -> Seq Scan on public.metric_name - Output: metric_name.name, metric_name.id -(19 rows) - --- An interesting special case is when the remote SQL has a parameter, but it is --- the result of an initplan. It's not "parameterized" in the join sense, because --- there is only one param value. This is the most efficient plan for querying a --- small number of ids. -explain (costs off, verbose) -select id, max(value) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_dist.id, max(metric_dist.value) - Group Key: metric_dist.id - InitPlan 1 (returns $0) - -> Aggregate - Output: array_agg(metric_name.id) - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.value - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND ((id = ANY ($1::integer[]))) ORDER BY id ASC NULLS LAST -(15 rows) - --- Multiple joins. Test both EC and non-EC (texteq) join in one query. -create table metric_location(id int, location text); -insert into metric_location values (1, 'Yerevan'), (3, 'Dilijan'), (7, 'Stepanakert'); -analyze metric_location; -select id, max(value) -from metric_dist natural join metric_location natural join metric_name -where name like 'cpu%' and texteq(location, 'Yerevan') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -; - id | max -----+------------------ - 1 | 49.9941974878311 -(1 row) - -explain (costs off, verbose) -select id, max(value) -from metric_dist natural join metric_location natural join metric_name -where name like 'cpu%' and texteq(location, 'Yerevan') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_dist.id, max(metric_dist.value) - Group Key: metric_dist.id - -> Sort - Output: metric_dist.id, metric_dist.value - Sort Key: metric_dist.id - -> Nested Loop - Output: metric_dist.id, metric_dist.value - -> Nested Loop - Output: metric_location.id, metric_name.id - Inner Unique: true - Join Filter: (metric_location.id = metric_name.id) - -> Seq Scan on public.metric_location - Output: metric_location.id, metric_location.location - Filter: texteq(metric_location.location, 'Yerevan'::text) - -> Index Scan using metric_name_name on public.metric_name - Output: metric_name.id, metric_name.name - Index Cond: ((metric_name.name >= 'cpu'::text) AND (metric_name.name < 'cpv'::text)) - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.value - Data node: data_node_1 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_52_chunk - Remote SQL: SELECT id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[3, 16, 20, 37, 52]) AND ((ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((ts <= '2022-03-02 15:02:02-08'::timestamp with time zone)) AND (($1::integer = id)) -(24 rows) - --- Multiple joins on different variables. Use a table instead of a CTE for saner --- stats. -create table max_value_times as -select distinct on (id) id, ts from metric_dist -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, value desc -; -analyze max_value_times; -explain (costs off, verbose) -select id, value -from metric_dist natural join max_value_times natural join metric_name -where name like 'cpu%' -order by 1 -; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: metric_dist.id, metric_dist.value - -> Nested Loop - Output: max_value_times.ts, max_value_times.id, metric_name.id - Join Filter: (max_value_times.id = metric_name.id) - -> Index Scan using metric_name_id on public.metric_name - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Seq Scan on public.max_value_times - Output: max_value_times.id, max_value_times.ts - -> Custom Scan (DataNodeScan) on public.metric_dist - Output: metric_dist.id, metric_dist.value, metric_dist.ts - Data node: data_node_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_17_chunk, _dist_hyper_1_18_chunk, _dist_hyper_1_19_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_21_chunk, _dist_hyper_1_22_chunk, _dist_hyper_1_23_chunk, _dist_hyper_1_24_chunk, _dist_hyper_1_25_chunk, _dist_hyper_1_26_chunk, _dist_hyper_1_27_chunk, _dist_hyper_1_28_chunk, _dist_hyper_1_29_chunk, _dist_hyper_1_30_chunk, _dist_hyper_1_31_chunk, _dist_hyper_1_32_chunk, _dist_hyper_1_33_chunk, _dist_hyper_1_34_chunk, _dist_hyper_1_35_chunk, _dist_hyper_1_36_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_38_chunk, _dist_hyper_1_39_chunk, _dist_hyper_1_40_chunk, _dist_hyper_1_41_chunk, _dist_hyper_1_42_chunk, _dist_hyper_1_43_chunk, _dist_hyper_1_44_chunk, _dist_hyper_1_45_chunk, _dist_hyper_1_46_chunk, _dist_hyper_1_47_chunk, _dist_hyper_1_48_chunk, _dist_hyper_1_49_chunk, _dist_hyper_1_50_chunk, _dist_hyper_1_51_chunk, _dist_hyper_1_52_chunk, _dist_hyper_1_53_chunk - Remote SQL: SELECT ts, id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53]) AND (($1::timestamp with time zone = ts)) AND (($2::integer = id)) -(15 rows) - --- Two distributed hypertables, each joined to reference and all joined together. --- The query finds the percentage of time points where one metric is higher than --- another, and also tweaked not to use initplans.Requires hash join. -explain (analyze, verbose, costs off, timing off, summary off) -select count(*) filter (where m1.value > m2.value) / count(*) -from metric_dist m1 -join metric_dist m2 using (ts) -where m1.id in (select id from metric_name where name = 'cpu1') - and m2.id in (select id from metric_name where name = 'cpu3') -; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=1) - Output: (count(*) FILTER (WHERE (m1.value > m2.value)) / count(*)) - -> Hash Join (actual rows=91 loops=1) - Output: m1.value, m2.value - Hash Cond: (m1.ts = m2.ts) - -> Nested Loop (actual rows=50037 loops=1) - Output: m1.value, m1.ts - -> Index Scan using metric_name_name on public.metric_name (actual rows=1 loops=1) - Output: metric_name.id, metric_name.name - Index Cond: (metric_name.name = 'cpu1'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist m1 (actual rows=50037 loops=1) - Output: m1.value, m1.ts, m1.id - Data node: data_node_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_17_chunk, _dist_hyper_1_18_chunk, _dist_hyper_1_19_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_21_chunk, _dist_hyper_1_22_chunk, _dist_hyper_1_23_chunk, _dist_hyper_1_24_chunk, _dist_hyper_1_25_chunk, _dist_hyper_1_26_chunk, _dist_hyper_1_27_chunk, _dist_hyper_1_28_chunk, _dist_hyper_1_29_chunk, _dist_hyper_1_30_chunk, _dist_hyper_1_31_chunk, _dist_hyper_1_32_chunk, _dist_hyper_1_33_chunk, _dist_hyper_1_34_chunk, _dist_hyper_1_35_chunk, _dist_hyper_1_36_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_38_chunk, _dist_hyper_1_39_chunk, _dist_hyper_1_40_chunk, _dist_hyper_1_41_chunk, _dist_hyper_1_42_chunk, _dist_hyper_1_43_chunk, _dist_hyper_1_44_chunk, _dist_hyper_1_45_chunk, _dist_hyper_1_46_chunk, _dist_hyper_1_47_chunk, _dist_hyper_1_48_chunk, _dist_hyper_1_49_chunk, _dist_hyper_1_50_chunk, _dist_hyper_1_51_chunk, _dist_hyper_1_52_chunk, _dist_hyper_1_53_chunk - Remote SQL: SELECT ts, id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53]) AND (($1::integer = id)) - -> Hash (actual rows=50101 loops=1) - Output: m2.value, m2.ts - Buckets: 65536 (originally 1024) Batches: 1 (originally 1) - -> Nested Loop (actual rows=50101 loops=1) - Output: m2.value, m2.ts - -> Index Scan using metric_name_name on public.metric_name metric_name_1 (actual rows=1 loops=1) - Output: metric_name_1.id, metric_name_1.name - Index Cond: (metric_name_1.name = 'cpu3'::text) - -> Custom Scan (DataNodeScan) on public.metric_dist m2 (actual rows=50101 loops=1) - Output: m2.value, m2.ts, m2.id - Data node: data_node_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_17_chunk, _dist_hyper_1_18_chunk, _dist_hyper_1_19_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_21_chunk, _dist_hyper_1_22_chunk, _dist_hyper_1_23_chunk, _dist_hyper_1_24_chunk, _dist_hyper_1_25_chunk, _dist_hyper_1_26_chunk, _dist_hyper_1_27_chunk, _dist_hyper_1_28_chunk, _dist_hyper_1_29_chunk, _dist_hyper_1_30_chunk, _dist_hyper_1_31_chunk, _dist_hyper_1_32_chunk, _dist_hyper_1_33_chunk, _dist_hyper_1_34_chunk, _dist_hyper_1_35_chunk, _dist_hyper_1_36_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_38_chunk, _dist_hyper_1_39_chunk, _dist_hyper_1_40_chunk, _dist_hyper_1_41_chunk, _dist_hyper_1_42_chunk, _dist_hyper_1_43_chunk, _dist_hyper_1_44_chunk, _dist_hyper_1_45_chunk, _dist_hyper_1_46_chunk, _dist_hyper_1_47_chunk, _dist_hyper_1_48_chunk, _dist_hyper_1_49_chunk, _dist_hyper_1_50_chunk, _dist_hyper_1_51_chunk, _dist_hyper_1_52_chunk, _dist_hyper_1_53_chunk - Remote SQL: SELECT ts, id, value FROM public.metric_dist WHERE _timescaledb_functions.chunks_in(public.metric_dist.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53]) AND (($1::integer = id)) -(30 rows) - --- Should prefer reference table join pushdown to all other kinds of plans, --- basically always. Note that we don't actually replicate the ref table here, --- so EXPLAIN ANALYZE would fail. -set role :ROLE_CLUSTER_SUPERUSER; -alter foreign data wrapper timescaledb_fdw options (add reference_tables 'metric_name'); -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' -group by name -order by name -; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Result - Output: metric_name.name, metric_dist.value - -> Custom Scan (DataNodeScan) - Output: metric_dist.value, metric_name.name - Data node: data_node_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_17_chunk, _dist_hyper_1_18_chunk, _dist_hyper_1_19_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_21_chunk, _dist_hyper_1_22_chunk, _dist_hyper_1_23_chunk, _dist_hyper_1_24_chunk, _dist_hyper_1_25_chunk, _dist_hyper_1_26_chunk, _dist_hyper_1_27_chunk, _dist_hyper_1_28_chunk, _dist_hyper_1_29_chunk, _dist_hyper_1_30_chunk, _dist_hyper_1_31_chunk, _dist_hyper_1_32_chunk, _dist_hyper_1_33_chunk, _dist_hyper_1_34_chunk, _dist_hyper_1_35_chunk, _dist_hyper_1_36_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_38_chunk, _dist_hyper_1_39_chunk, _dist_hyper_1_40_chunk, _dist_hyper_1_41_chunk, _dist_hyper_1_42_chunk, _dist_hyper_1_43_chunk, _dist_hyper_1_44_chunk, _dist_hyper_1_45_chunk, _dist_hyper_1_46_chunk, _dist_hyper_1_47_chunk, _dist_hyper_1_48_chunk, _dist_hyper_1_49_chunk, _dist_hyper_1_50_chunk, _dist_hyper_1_51_chunk, _dist_hyper_1_52_chunk, _dist_hyper_1_53_chunk - Remote SQL: SELECT r57.value, r2.name FROM (public.metric_dist r57 INNER JOIN public.metric_name r2 ON (((r57.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r57, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53]) ORDER BY r2.name ASC NULLS LAST -(10 rows) - -set timescaledb.enable_parameterized_data_node_scan to false; -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' -group by name -order by name -; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: metric_name.name, max(metric_dist.value), count(*) - Group Key: metric_name.name - -> Result - Output: metric_name.name, metric_dist.value - -> Custom Scan (DataNodeScan) - Output: metric_dist.value, metric_name.name - Data node: data_node_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_16_chunk, _dist_hyper_1_17_chunk, _dist_hyper_1_18_chunk, _dist_hyper_1_19_chunk, _dist_hyper_1_20_chunk, _dist_hyper_1_21_chunk, _dist_hyper_1_22_chunk, _dist_hyper_1_23_chunk, _dist_hyper_1_24_chunk, _dist_hyper_1_25_chunk, _dist_hyper_1_26_chunk, _dist_hyper_1_27_chunk, _dist_hyper_1_28_chunk, _dist_hyper_1_29_chunk, _dist_hyper_1_30_chunk, _dist_hyper_1_31_chunk, _dist_hyper_1_32_chunk, _dist_hyper_1_33_chunk, _dist_hyper_1_34_chunk, _dist_hyper_1_35_chunk, _dist_hyper_1_36_chunk, _dist_hyper_1_37_chunk, _dist_hyper_1_38_chunk, _dist_hyper_1_39_chunk, _dist_hyper_1_40_chunk, _dist_hyper_1_41_chunk, _dist_hyper_1_42_chunk, _dist_hyper_1_43_chunk, _dist_hyper_1_44_chunk, _dist_hyper_1_45_chunk, _dist_hyper_1_46_chunk, _dist_hyper_1_47_chunk, _dist_hyper_1_48_chunk, _dist_hyper_1_49_chunk, _dist_hyper_1_50_chunk, _dist_hyper_1_51_chunk, _dist_hyper_1_52_chunk, _dist_hyper_1_53_chunk - Remote SQL: SELECT r57.value, r2.name FROM (public.metric_dist r57 INNER JOIN public.metric_name r2 ON (((r57.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r57, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53]) ORDER BY r2.name ASC NULLS LAST -(10 rows) - diff --git a/tsl/test/expected/dist_partial_agg-13.out b/tsl/test/expected/dist_partial_agg-13.out deleted file mode 100644 index 53e6b319e85..00000000000 --- a/tsl/test/expected/dist_partial_agg-13.out +++ /dev/null @@ -1,612 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SET ROLE :ROLE_1; -\set TEST_TABLE 'conditions' -\ir 'include/aggregate_table_create.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. --- This file creates a table with a lot of different types to allow a range of aggregate functions. --- This does not include the creation of a corresponding hypertable, as we may want to vary how that is done. -CREATE TYPE custom_type AS (high int, low int); -CREATE TABLE :TEST_TABLE ( - timec TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - region TEXT NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL, - lowp double precision NULL, - highp double precision null, - allnull double precision null, - highlow custom_type null, - bit_int smallint, - good_life boolean - ); -SET ROLE :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_partial_agg_1 | db_dist_partial_agg_1 | t | t | t - db_dist_partial_agg_2 | db_dist_partial_agg_2 | t | t | t - db_dist_partial_agg_3 | db_dist_partial_agg_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -SELECT * FROM test.remote_exec('{ db_dist_partial_agg_1, db_dist_partial_agg_2, db_dist_partial_agg_3}', -$$ - CREATE TYPE custom_type AS (high int, low int); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_partial_agg_1]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_2]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_3]: - CREATE TYPE custom_type AS (high int, low int) - remote_exec -------------- - -(1 row) - -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DATA_NODE_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_3 SET parallel_setup_cost TO 1; --- make sure partitionwise aggregation is enabled on data nodes -ALTER DATABASE :DATA_NODE_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_3 SET enable_partitionwise_aggregate TO true; -SET ROLE :ROLE_1; -SELECT table_name FROM create_distributed_hypertable( 'conditions', 'timec', 'location', 3, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - --- We need a lot of data and a lot of chunks to make the planner push down all of the aggregates -\ir 'include/aggregate_table_populate.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'POR', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SFO', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SEA', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'TAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'NYC', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'BOS', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'CHI', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'MIN', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DET', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'LA', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SDG', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'PHX', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DAL', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'AUS', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -SET enable_partitionwise_aggregate = ON; -SET timescaledb.remote_data_fetcher = 'cursor'; --- Run an explain on the aggregate queries to make sure expected aggregates are being pushed down. --- Grouping by the paritioning column should result in full aggregate pushdown where possible, --- while using a non-partitioning column should result in a partial pushdown -\set PREFIX 'EXPLAIN (VERBOSE, COSTS OFF)' -\set GROUPING 'location' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, (min(allnull)), (max(temperature)), ((sum(temperature) + sum(humidity))), (avg(humidity)), (round(stddev((humidity)::integer), 5)), (bit_and(bit_int)), (bit_or(bit_int)), (bool_and(good_life)), (every((temperature > '0'::double precision))), (bool_or(good_life)), (count(*)), (count(temperature)), (count(allnull)), (round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round(stddev((temperature)::integer), 5)), (round(stddev_pop((temperature)::integer), 5)), (round(stddev_samp((temperature)::integer), 5)), (round(variance((temperature)::integer), 5)), (round(var_pop((temperature)::integer), 5)), (round(var_samp((temperature)::integer), 5)), (last(temperature, timec)), (histogram(temperature, '0'::double precision, '100'::double precision, 1)), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, (min(conditions.allnull)), (max(conditions.temperature)), ((sum(conditions.temperature) + sum(conditions.humidity))), (avg(conditions.humidity)), (round(stddev((conditions.humidity)::integer), 5)), (bit_and(conditions.bit_int)), (bit_or(conditions.bit_int)), (bool_and(conditions.good_life)), (every((conditions.temperature > '0'::double precision))), (bool_or(conditions.good_life)), (count(*)), (count(conditions.temperature)), (count(conditions.allnull)), (round((corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions.temperature)::integer), 5)), (round(stddev_pop((conditions.temperature)::integer), 5)), (round(stddev_samp((conditions.temperature)::integer), 5)), (round(variance((conditions.temperature)::integer), 5)), (round(var_pop((conditions.temperature)::integer), 5)), (round(var_samp((conditions.temperature)::integer), 5)), (last(conditions.temperature, conditions.timec)), (histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, (min(conditions_1.allnull)), (max(conditions_1.temperature)), ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), (avg(conditions_1.humidity)), (round(stddev((conditions_1.humidity)::integer), 5)), (bit_and(conditions_1.bit_int)), (bit_or(conditions_1.bit_int)), (bool_and(conditions_1.good_life)), (every((conditions_1.temperature > '0'::double precision))), (bool_or(conditions_1.good_life)), (count(*)), (count(conditions_1.temperature)), (count(conditions_1.allnull)), (round((corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_1.temperature)::integer), 5)), (round(stddev_pop((conditions_1.temperature)::integer), 5)), (round(stddev_samp((conditions_1.temperature)::integer), 5)), (round(variance((conditions_1.temperature)::integer), 5)), (round(var_pop((conditions_1.temperature)::integer), 5)), (round(var_samp((conditions_1.temperature)::integer), 5)), (last(conditions_1.temperature, conditions_1.timec)), (histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, (min(conditions_2.allnull)), (max(conditions_2.temperature)), ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), (avg(conditions_2.humidity)), (round(stddev((conditions_2.humidity)::integer), 5)), (bit_and(conditions_2.bit_int)), (bit_or(conditions_2.bit_int)), (bool_and(conditions_2.good_life)), (every((conditions_2.temperature > '0'::double precision))), (bool_or(conditions_2.good_life)), (count(*)), (count(conditions_2.temperature)), (count(conditions_2.allnull)), (round((corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_2.temperature)::integer), 5)), (round(stddev_pop((conditions_2.temperature)::integer), 5)), (round(stddev_samp((conditions_2.temperature)::integer), 5)), (round(variance((conditions_2.temperature)::integer), 5)), (round(var_pop((conditions_2.temperature)::integer), 5)), (round(var_samp((conditions_2.temperature)::integer), 5)), (last(conditions_2.temperature, conditions_2.timec)), (histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.timec, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, last(conditions_1.highlow, conditions_1.timec), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.timec, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, last(conditions_2.highlow, conditions_2.timec), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.timec, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.timec, conditions.allnull, conditions.temperature, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, min(conditions_1.allnull), max(conditions_1.temperature), (sum(conditions_1.temperature) + sum(conditions_1.humidity)), avg(conditions_1.humidity), round(stddev((conditions_1.humidity)::integer), 5), bit_and(conditions_1.bit_int), bit_or(conditions_1.bit_int), bool_and(conditions_1.good_life), every((conditions_1.temperature > '0'::double precision)), bool_or(conditions_1.good_life), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.timec, conditions_1.allnull, conditions_1.temperature, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, min(conditions_2.allnull), max(conditions_2.temperature), (sum(conditions_2.temperature) + sum(conditions_2.humidity)), avg(conditions_2.humidity), round(stddev((conditions_2.humidity)::integer), 5), bit_and(conditions_2.bit_int), bit_or(conditions_2.bit_int), bool_and(conditions_2.good_life), every((conditions_2.temperature > '0'::double precision)), bool_or(conditions_2.good_life), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.timec, conditions_2.allnull, conditions_2.temperature, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: location, ((sum(temperature) + sum(humidity))), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, ((sum(conditions.temperature) + sum(conditions.humidity))), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - -\set GROUPING 'region, temperature' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev((humidity)::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > '0'::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round(stddev((temperature)::integer), 5), round(stddev_pop((temperature)::integer), 5), round(stddev_samp((temperature)::integer), 5), round(variance((temperature)::integer), 5), round(var_pop((temperature)::integer), 5), round(var_samp((temperature)::integer), 5), last(temperature, timec), histogram(temperature, '0'::double precision, '100'::double precision, 1), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL min(allnull)), (PARTIAL max(temperature)), (PARTIAL sum(temperature)), (PARTIAL sum(humidity)), (PARTIAL avg(humidity)), (PARTIAL stddev((humidity)::integer)), (PARTIAL bit_and(bit_int)), (PARTIAL bit_or(bit_int)), (PARTIAL bool_and(good_life)), (PARTIAL every((temperature > '0'::double precision))), (PARTIAL bool_or(good_life)), (PARTIAL count(*)), (PARTIAL count(temperature)), (PARTIAL count(allnull)), (PARTIAL corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL stddev((temperature)::integer)), (PARTIAL stddev_pop((temperature)::integer)), (PARTIAL stddev_samp((temperature)::integer)), (PARTIAL variance((temperature)::integer)), (PARTIAL var_pop((temperature)::integer)), (PARTIAL var_samp((temperature)::integer)), (PARTIAL last(temperature, timec)), (PARTIAL histogram(temperature, '0'::double precision, '100'::double precision, 1)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL min(conditions.allnull)), (PARTIAL max(conditions.temperature)), (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)), (PARTIAL avg(conditions.humidity)), (PARTIAL stddev((conditions.humidity)::integer)), (PARTIAL bit_and(conditions.bit_int)), (PARTIAL bit_or(conditions.bit_int)), (PARTIAL bool_and(conditions.good_life)), (PARTIAL every((conditions.temperature > '0'::double precision))), (PARTIAL bool_or(conditions.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions.temperature)), (PARTIAL count(conditions.allnull)), (PARTIAL corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL stddev((conditions.temperature)::integer)), (PARTIAL stddev_pop((conditions.temperature)::integer)), (PARTIAL stddev_samp((conditions.temperature)::integer)), (PARTIAL variance((conditions.temperature)::integer)), (PARTIAL var_pop((conditions.temperature)::integer)), (PARTIAL var_samp((conditions.temperature)::integer)), (PARTIAL last(conditions.temperature, conditions.timec)), (PARTIAL histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL min(conditions_1.allnull)), (PARTIAL max(conditions_1.temperature)), (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)), (PARTIAL avg(conditions_1.humidity)), (PARTIAL stddev((conditions_1.humidity)::integer)), (PARTIAL bit_and(conditions_1.bit_int)), (PARTIAL bit_or(conditions_1.bit_int)), (PARTIAL bool_and(conditions_1.good_life)), (PARTIAL every((conditions_1.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_1.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_1.temperature)), (PARTIAL count(conditions_1.allnull)), (PARTIAL corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_1.temperature)::integer)), (PARTIAL stddev_pop((conditions_1.temperature)::integer)), (PARTIAL stddev_samp((conditions_1.temperature)::integer)), (PARTIAL variance((conditions_1.temperature)::integer)), (PARTIAL var_pop((conditions_1.temperature)::integer)), (PARTIAL var_samp((conditions_1.temperature)::integer)), (PARTIAL last(conditions_1.temperature, conditions_1.timec)), (PARTIAL histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL min(conditions_2.allnull)), (PARTIAL max(conditions_2.temperature)), (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)), (PARTIAL avg(conditions_2.humidity)), (PARTIAL stddev((conditions_2.humidity)::integer)), (PARTIAL bit_and(conditions_2.bit_int)), (PARTIAL bit_or(conditions_2.bit_int)), (PARTIAL bool_and(conditions_2.good_life)), (PARTIAL every((conditions_2.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_2.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_2.temperature)), (PARTIAL count(conditions_2.allnull)), (PARTIAL corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_2.temperature)::integer)), (PARTIAL stddev_pop((conditions_2.temperature)::integer)), (PARTIAL stddev_samp((conditions_2.temperature)::integer)), (PARTIAL variance((conditions_2.temperature)::integer)), (PARTIAL var_pop((conditions_2.temperature)::integer)), (PARTIAL var_samp((conditions_2.temperature)::integer)), (PARTIAL last(conditions_2.temperature, conditions_2.timec)), (PARTIAL histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL last(conditions.highlow, conditions.timec), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.timec, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL last(conditions_1.highlow, conditions_1.timec), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL last(conditions_2.highlow, conditions_2.timec), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(29 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL min(conditions.allnull), PARTIAL max(conditions.temperature), PARTIAL sum(conditions.temperature), PARTIAL sum(conditions.humidity), PARTIAL avg(conditions.humidity), PARTIAL stddev((conditions.humidity)::integer), PARTIAL bit_and(conditions.bit_int), PARTIAL bit_or(conditions.bit_int), PARTIAL bool_and(conditions.good_life), PARTIAL every((conditions.temperature > '0'::double precision)), PARTIAL bool_or(conditions.good_life), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.timec, conditions.allnull, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL min(conditions_1.allnull), PARTIAL max(conditions_1.temperature), PARTIAL sum(conditions_1.temperature), PARTIAL sum(conditions_1.humidity), PARTIAL avg(conditions_1.humidity), PARTIAL stddev((conditions_1.humidity)::integer), PARTIAL bit_and(conditions_1.bit_int), PARTIAL bit_or(conditions_1.bit_int), PARTIAL bool_and(conditions_1.good_life), PARTIAL every((conditions_1.temperature > '0'::double precision)), PARTIAL bool_or(conditions_1.good_life), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.allnull, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL min(conditions_2.allnull), PARTIAL max(conditions_2.temperature), PARTIAL sum(conditions_2.temperature), PARTIAL sum(conditions_2.humidity), PARTIAL avg(conditions_2.humidity), PARTIAL stddev((conditions_2.humidity)::integer), PARTIAL bit_and(conditions_2.bit_int), PARTIAL bit_or(conditions_2.bit_int), PARTIAL bool_and(conditions_2.good_life), PARTIAL every((conditions_2.temperature > '0'::double precision)), PARTIAL bool_or(conditions_2.good_life), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.allnull, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(29 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, (sum(temperature) + sum(humidity)), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL sum(temperature)), (PARTIAL sum(humidity)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, timec - Group Key: region, temperature, timec - Filter: (avg(temperature) > '20'::double precision) - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL avg(temperature)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL avg(conditions.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL avg(conditions_1.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL avg(conditions_2.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Full aggregate pushdown correctness check, compare location grouped query results with partionwise aggregates on and off -\set GROUPING 'location' -SELECT format('%s/results/dist_agg_loc_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST1", - format('%s/results/dist_agg_loc_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL1" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL1', :'RESULTS_TEST1') as "DIFF_CMD1" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD1 --- Partial aggregate pushdown correctness check, compare region grouped query results with partionwise aggregates on and off -\set GROUPING 'region' -SELECT format('%s/results/dist_agg_region_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST2", - format('%s/results/dist_agg_region_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL2" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL2', :'RESULTS_TEST2') as "DIFF_CMD2" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_partial_agg-14.out b/tsl/test/expected/dist_partial_agg-14.out deleted file mode 100644 index 53e6b319e85..00000000000 --- a/tsl/test/expected/dist_partial_agg-14.out +++ /dev/null @@ -1,612 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SET ROLE :ROLE_1; -\set TEST_TABLE 'conditions' -\ir 'include/aggregate_table_create.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. --- This file creates a table with a lot of different types to allow a range of aggregate functions. --- This does not include the creation of a corresponding hypertable, as we may want to vary how that is done. -CREATE TYPE custom_type AS (high int, low int); -CREATE TABLE :TEST_TABLE ( - timec TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - region TEXT NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL, - lowp double precision NULL, - highp double precision null, - allnull double precision null, - highlow custom_type null, - bit_int smallint, - good_life boolean - ); -SET ROLE :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_partial_agg_1 | db_dist_partial_agg_1 | t | t | t - db_dist_partial_agg_2 | db_dist_partial_agg_2 | t | t | t - db_dist_partial_agg_3 | db_dist_partial_agg_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -SELECT * FROM test.remote_exec('{ db_dist_partial_agg_1, db_dist_partial_agg_2, db_dist_partial_agg_3}', -$$ - CREATE TYPE custom_type AS (high int, low int); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_partial_agg_1]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_2]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_3]: - CREATE TYPE custom_type AS (high int, low int) - remote_exec -------------- - -(1 row) - -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DATA_NODE_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_3 SET parallel_setup_cost TO 1; --- make sure partitionwise aggregation is enabled on data nodes -ALTER DATABASE :DATA_NODE_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_3 SET enable_partitionwise_aggregate TO true; -SET ROLE :ROLE_1; -SELECT table_name FROM create_distributed_hypertable( 'conditions', 'timec', 'location', 3, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - --- We need a lot of data and a lot of chunks to make the planner push down all of the aggregates -\ir 'include/aggregate_table_populate.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'POR', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SFO', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SEA', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'TAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'NYC', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'BOS', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'CHI', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'MIN', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DET', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'LA', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SDG', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'PHX', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DAL', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'AUS', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -SET enable_partitionwise_aggregate = ON; -SET timescaledb.remote_data_fetcher = 'cursor'; --- Run an explain on the aggregate queries to make sure expected aggregates are being pushed down. --- Grouping by the paritioning column should result in full aggregate pushdown where possible, --- while using a non-partitioning column should result in a partial pushdown -\set PREFIX 'EXPLAIN (VERBOSE, COSTS OFF)' -\set GROUPING 'location' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, (min(allnull)), (max(temperature)), ((sum(temperature) + sum(humidity))), (avg(humidity)), (round(stddev((humidity)::integer), 5)), (bit_and(bit_int)), (bit_or(bit_int)), (bool_and(good_life)), (every((temperature > '0'::double precision))), (bool_or(good_life)), (count(*)), (count(temperature)), (count(allnull)), (round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round(stddev((temperature)::integer), 5)), (round(stddev_pop((temperature)::integer), 5)), (round(stddev_samp((temperature)::integer), 5)), (round(variance((temperature)::integer), 5)), (round(var_pop((temperature)::integer), 5)), (round(var_samp((temperature)::integer), 5)), (last(temperature, timec)), (histogram(temperature, '0'::double precision, '100'::double precision, 1)), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, (min(conditions.allnull)), (max(conditions.temperature)), ((sum(conditions.temperature) + sum(conditions.humidity))), (avg(conditions.humidity)), (round(stddev((conditions.humidity)::integer), 5)), (bit_and(conditions.bit_int)), (bit_or(conditions.bit_int)), (bool_and(conditions.good_life)), (every((conditions.temperature > '0'::double precision))), (bool_or(conditions.good_life)), (count(*)), (count(conditions.temperature)), (count(conditions.allnull)), (round((corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions.temperature)::integer), 5)), (round(stddev_pop((conditions.temperature)::integer), 5)), (round(stddev_samp((conditions.temperature)::integer), 5)), (round(variance((conditions.temperature)::integer), 5)), (round(var_pop((conditions.temperature)::integer), 5)), (round(var_samp((conditions.temperature)::integer), 5)), (last(conditions.temperature, conditions.timec)), (histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, (min(conditions_1.allnull)), (max(conditions_1.temperature)), ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), (avg(conditions_1.humidity)), (round(stddev((conditions_1.humidity)::integer), 5)), (bit_and(conditions_1.bit_int)), (bit_or(conditions_1.bit_int)), (bool_and(conditions_1.good_life)), (every((conditions_1.temperature > '0'::double precision))), (bool_or(conditions_1.good_life)), (count(*)), (count(conditions_1.temperature)), (count(conditions_1.allnull)), (round((corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_1.temperature)::integer), 5)), (round(stddev_pop((conditions_1.temperature)::integer), 5)), (round(stddev_samp((conditions_1.temperature)::integer), 5)), (round(variance((conditions_1.temperature)::integer), 5)), (round(var_pop((conditions_1.temperature)::integer), 5)), (round(var_samp((conditions_1.temperature)::integer), 5)), (last(conditions_1.temperature, conditions_1.timec)), (histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, (min(conditions_2.allnull)), (max(conditions_2.temperature)), ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), (avg(conditions_2.humidity)), (round(stddev((conditions_2.humidity)::integer), 5)), (bit_and(conditions_2.bit_int)), (bit_or(conditions_2.bit_int)), (bool_and(conditions_2.good_life)), (every((conditions_2.temperature > '0'::double precision))), (bool_or(conditions_2.good_life)), (count(*)), (count(conditions_2.temperature)), (count(conditions_2.allnull)), (round((corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_2.temperature)::integer), 5)), (round(stddev_pop((conditions_2.temperature)::integer), 5)), (round(stddev_samp((conditions_2.temperature)::integer), 5)), (round(variance((conditions_2.temperature)::integer), 5)), (round(var_pop((conditions_2.temperature)::integer), 5)), (round(var_samp((conditions_2.temperature)::integer), 5)), (last(conditions_2.temperature, conditions_2.timec)), (histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.timec, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, last(conditions_1.highlow, conditions_1.timec), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.timec, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, last(conditions_2.highlow, conditions_2.timec), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.timec, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.timec, conditions.allnull, conditions.temperature, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, min(conditions_1.allnull), max(conditions_1.temperature), (sum(conditions_1.temperature) + sum(conditions_1.humidity)), avg(conditions_1.humidity), round(stddev((conditions_1.humidity)::integer), 5), bit_and(conditions_1.bit_int), bit_or(conditions_1.bit_int), bool_and(conditions_1.good_life), every((conditions_1.temperature > '0'::double precision)), bool_or(conditions_1.good_life), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.timec, conditions_1.allnull, conditions_1.temperature, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, min(conditions_2.allnull), max(conditions_2.temperature), (sum(conditions_2.temperature) + sum(conditions_2.humidity)), avg(conditions_2.humidity), round(stddev((conditions_2.humidity)::integer), 5), bit_and(conditions_2.bit_int), bit_or(conditions_2.bit_int), bool_and(conditions_2.good_life), every((conditions_2.temperature > '0'::double precision)), bool_or(conditions_2.good_life), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.timec, conditions_2.allnull, conditions_2.temperature, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: location, ((sum(temperature) + sum(humidity))), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, ((sum(conditions.temperature) + sum(conditions.humidity))), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - -\set GROUPING 'region, temperature' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev((humidity)::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > '0'::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round(stddev((temperature)::integer), 5), round(stddev_pop((temperature)::integer), 5), round(stddev_samp((temperature)::integer), 5), round(variance((temperature)::integer), 5), round(var_pop((temperature)::integer), 5), round(var_samp((temperature)::integer), 5), last(temperature, timec), histogram(temperature, '0'::double precision, '100'::double precision, 1), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL min(allnull)), (PARTIAL max(temperature)), (PARTIAL sum(temperature)), (PARTIAL sum(humidity)), (PARTIAL avg(humidity)), (PARTIAL stddev((humidity)::integer)), (PARTIAL bit_and(bit_int)), (PARTIAL bit_or(bit_int)), (PARTIAL bool_and(good_life)), (PARTIAL every((temperature > '0'::double precision))), (PARTIAL bool_or(good_life)), (PARTIAL count(*)), (PARTIAL count(temperature)), (PARTIAL count(allnull)), (PARTIAL corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL stddev((temperature)::integer)), (PARTIAL stddev_pop((temperature)::integer)), (PARTIAL stddev_samp((temperature)::integer)), (PARTIAL variance((temperature)::integer)), (PARTIAL var_pop((temperature)::integer)), (PARTIAL var_samp((temperature)::integer)), (PARTIAL last(temperature, timec)), (PARTIAL histogram(temperature, '0'::double precision, '100'::double precision, 1)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL min(conditions.allnull)), (PARTIAL max(conditions.temperature)), (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)), (PARTIAL avg(conditions.humidity)), (PARTIAL stddev((conditions.humidity)::integer)), (PARTIAL bit_and(conditions.bit_int)), (PARTIAL bit_or(conditions.bit_int)), (PARTIAL bool_and(conditions.good_life)), (PARTIAL every((conditions.temperature > '0'::double precision))), (PARTIAL bool_or(conditions.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions.temperature)), (PARTIAL count(conditions.allnull)), (PARTIAL corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL stddev((conditions.temperature)::integer)), (PARTIAL stddev_pop((conditions.temperature)::integer)), (PARTIAL stddev_samp((conditions.temperature)::integer)), (PARTIAL variance((conditions.temperature)::integer)), (PARTIAL var_pop((conditions.temperature)::integer)), (PARTIAL var_samp((conditions.temperature)::integer)), (PARTIAL last(conditions.temperature, conditions.timec)), (PARTIAL histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL min(conditions_1.allnull)), (PARTIAL max(conditions_1.temperature)), (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)), (PARTIAL avg(conditions_1.humidity)), (PARTIAL stddev((conditions_1.humidity)::integer)), (PARTIAL bit_and(conditions_1.bit_int)), (PARTIAL bit_or(conditions_1.bit_int)), (PARTIAL bool_and(conditions_1.good_life)), (PARTIAL every((conditions_1.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_1.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_1.temperature)), (PARTIAL count(conditions_1.allnull)), (PARTIAL corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_1.temperature)::integer)), (PARTIAL stddev_pop((conditions_1.temperature)::integer)), (PARTIAL stddev_samp((conditions_1.temperature)::integer)), (PARTIAL variance((conditions_1.temperature)::integer)), (PARTIAL var_pop((conditions_1.temperature)::integer)), (PARTIAL var_samp((conditions_1.temperature)::integer)), (PARTIAL last(conditions_1.temperature, conditions_1.timec)), (PARTIAL histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL min(conditions_2.allnull)), (PARTIAL max(conditions_2.temperature)), (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)), (PARTIAL avg(conditions_2.humidity)), (PARTIAL stddev((conditions_2.humidity)::integer)), (PARTIAL bit_and(conditions_2.bit_int)), (PARTIAL bit_or(conditions_2.bit_int)), (PARTIAL bool_and(conditions_2.good_life)), (PARTIAL every((conditions_2.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_2.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_2.temperature)), (PARTIAL count(conditions_2.allnull)), (PARTIAL corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_2.temperature)::integer)), (PARTIAL stddev_pop((conditions_2.temperature)::integer)), (PARTIAL stddev_samp((conditions_2.temperature)::integer)), (PARTIAL variance((conditions_2.temperature)::integer)), (PARTIAL var_pop((conditions_2.temperature)::integer)), (PARTIAL var_samp((conditions_2.temperature)::integer)), (PARTIAL last(conditions_2.temperature, conditions_2.timec)), (PARTIAL histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL last(conditions.highlow, conditions.timec), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.timec, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL last(conditions_1.highlow, conditions_1.timec), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL last(conditions_2.highlow, conditions_2.timec), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(29 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL min(conditions.allnull), PARTIAL max(conditions.temperature), PARTIAL sum(conditions.temperature), PARTIAL sum(conditions.humidity), PARTIAL avg(conditions.humidity), PARTIAL stddev((conditions.humidity)::integer), PARTIAL bit_and(conditions.bit_int), PARTIAL bit_or(conditions.bit_int), PARTIAL bool_and(conditions.good_life), PARTIAL every((conditions.temperature > '0'::double precision)), PARTIAL bool_or(conditions.good_life), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.timec, conditions.allnull, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL min(conditions_1.allnull), PARTIAL max(conditions_1.temperature), PARTIAL sum(conditions_1.temperature), PARTIAL sum(conditions_1.humidity), PARTIAL avg(conditions_1.humidity), PARTIAL stddev((conditions_1.humidity)::integer), PARTIAL bit_and(conditions_1.bit_int), PARTIAL bit_or(conditions_1.bit_int), PARTIAL bool_and(conditions_1.good_life), PARTIAL every((conditions_1.temperature > '0'::double precision)), PARTIAL bool_or(conditions_1.good_life), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.allnull, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL min(conditions_2.allnull), PARTIAL max(conditions_2.temperature), PARTIAL sum(conditions_2.temperature), PARTIAL sum(conditions_2.humidity), PARTIAL avg(conditions_2.humidity), PARTIAL stddev((conditions_2.humidity)::integer), PARTIAL bit_and(conditions_2.bit_int), PARTIAL bit_or(conditions_2.bit_int), PARTIAL bool_and(conditions_2.good_life), PARTIAL every((conditions_2.temperature > '0'::double precision)), PARTIAL bool_or(conditions_2.good_life), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.allnull, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(29 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, (sum(temperature) + sum(humidity)), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL sum(temperature)), (PARTIAL sum(humidity)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, timec - Group Key: region, temperature, timec - Filter: (avg(temperature) > '20'::double precision) - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL avg(temperature)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL avg(conditions.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL avg(conditions_1.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL avg(conditions_2.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Full aggregate pushdown correctness check, compare location grouped query results with partionwise aggregates on and off -\set GROUPING 'location' -SELECT format('%s/results/dist_agg_loc_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST1", - format('%s/results/dist_agg_loc_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL1" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL1', :'RESULTS_TEST1') as "DIFF_CMD1" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD1 --- Partial aggregate pushdown correctness check, compare region grouped query results with partionwise aggregates on and off -\set GROUPING 'region' -SELECT format('%s/results/dist_agg_region_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST2", - format('%s/results/dist_agg_region_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL2" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL2', :'RESULTS_TEST2') as "DIFF_CMD2" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_partial_agg-15.out b/tsl/test/expected/dist_partial_agg-15.out deleted file mode 100644 index 6a1d81c2e7b..00000000000 --- a/tsl/test/expected/dist_partial_agg-15.out +++ /dev/null @@ -1,636 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -SET ROLE :ROLE_1; -\set TEST_TABLE 'conditions' -\ir 'include/aggregate_table_create.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. --- This file creates a table with a lot of different types to allow a range of aggregate functions. --- This does not include the creation of a corresponding hypertable, as we may want to vary how that is done. -CREATE TYPE custom_type AS (high int, low int); -CREATE TABLE :TEST_TABLE ( - timec TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - region TEXT NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL, - lowp double precision NULL, - highp double precision null, - allnull double precision null, - highlow custom_type null, - bit_int smallint, - good_life boolean - ); -SET ROLE :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------------+-----------------------+--------------+------------------+------------------- - db_dist_partial_agg_1 | db_dist_partial_agg_1 | t | t | t - db_dist_partial_agg_2 | db_dist_partial_agg_2 | t | t | t - db_dist_partial_agg_3 | db_dist_partial_agg_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -SELECT * FROM test.remote_exec('{ db_dist_partial_agg_1, db_dist_partial_agg_2, db_dist_partial_agg_3}', -$$ - CREATE TYPE custom_type AS (high int, low int); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_partial_agg_1]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_2]: - CREATE TYPE custom_type AS (high int, low int) -NOTICE: [db_dist_partial_agg_3]: - CREATE TYPE custom_type AS (high int, low int) - remote_exec -------------- - -(1 row) - -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DATA_NODE_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_3 SET parallel_setup_cost TO 1; --- make sure partitionwise aggregation is enabled on data nodes -ALTER DATABASE :DATA_NODE_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_3 SET enable_partitionwise_aggregate TO true; -SET ROLE :ROLE_1; -SELECT table_name FROM create_distributed_hypertable( 'conditions', 'timec', 'location', 3, chunk_time_interval => INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated - table_name ------------- - conditions -(1 row) - --- We need a lot of data and a lot of chunks to make the planner push down all of the aggregates -\ir 'include/aggregate_table_populate.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'POR', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SFO', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SEA', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'TAC', 'west', generate_series(25, 85, 0.0625), 75, 40, 70, NULL, (1,2)::custom_type, 2, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'NYC', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'BOS', 'north-east', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'CHI', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'MIN', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DET', 'midwest', generate_series(29, 41, 0.0125), 45, 50, 40, NULL, (3,4)::custom_type, 4, false; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'LA', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'SDG', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'PHX', 'west', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'DAL', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -INSERT INTO :TEST_TABLE -SELECT generate_series('2018-12-01 00:00'::timestamp, '2018-12-04 08:00'::timestamp, '5 minute'), 'AUS', 'south', generate_series(61, 85, 0.025), 55, NULL, 28, NULL, NULL, 8, true; -SET enable_partitionwise_aggregate = ON; -SET timescaledb.remote_data_fetcher = 'cursor'; --- Run an explain on the aggregate queries to make sure expected aggregates are being pushed down. --- Grouping by the paritioning column should result in full aggregate pushdown where possible, --- while using a non-partitioning column should result in a partial pushdown -\set PREFIX 'EXPLAIN (VERBOSE, COSTS OFF)' -\set GROUPING 'location' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, (min(allnull)), (max(temperature)), ((sum(temperature) + sum(humidity))), (avg(humidity)), (round(stddev((humidity)::integer), 5)), (bit_and(bit_int)), (bit_or(bit_int)), (bool_and(good_life)), (every((temperature > '0'::double precision))), (bool_or(good_life)), (count(*)), (count(temperature)), (count(allnull)), (round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5)), (round(stddev((temperature)::integer), 5)), (round(stddev_pop((temperature)::integer), 5)), (round(stddev_samp((temperature)::integer), 5)), (round(variance((temperature)::integer), 5)), (round(var_pop((temperature)::integer), 5)), (round(var_samp((temperature)::integer), 5)), (last(temperature, timec)), (histogram(temperature, '0'::double precision, '100'::double precision, 1)), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, (min(conditions.allnull)), (max(conditions.temperature)), ((sum(conditions.temperature) + sum(conditions.humidity))), (avg(conditions.humidity)), (round(stddev((conditions.humidity)::integer), 5)), (bit_and(conditions.bit_int)), (bit_or(conditions.bit_int)), (bool_and(conditions.good_life)), (every((conditions.temperature > '0'::double precision))), (bool_or(conditions.good_life)), (count(*)), (count(conditions.temperature)), (count(conditions.allnull)), (round((corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions.temperature)::integer), 5)), (round(stddev_pop((conditions.temperature)::integer), 5)), (round(stddev_samp((conditions.temperature)::integer), 5)), (round(variance((conditions.temperature)::integer), 5)), (round(var_pop((conditions.temperature)::integer), 5)), (round(var_samp((conditions.temperature)::integer), 5)), (last(conditions.temperature, conditions.timec)), (histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, (min(conditions_1.allnull)), (max(conditions_1.temperature)), ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), (avg(conditions_1.humidity)), (round(stddev((conditions_1.humidity)::integer), 5)), (bit_and(conditions_1.bit_int)), (bit_or(conditions_1.bit_int)), (bool_and(conditions_1.good_life)), (every((conditions_1.temperature > '0'::double precision))), (bool_or(conditions_1.good_life)), (count(*)), (count(conditions_1.temperature)), (count(conditions_1.allnull)), (round((corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_1.temperature)::integer), 5)), (round(stddev_pop((conditions_1.temperature)::integer), 5)), (round(stddev_samp((conditions_1.temperature)::integer), 5)), (round(variance((conditions_1.temperature)::integer), 5)), (round(var_pop((conditions_1.temperature)::integer), 5)), (round(var_samp((conditions_1.temperature)::integer), 5)), (last(conditions_1.temperature, conditions_1.timec)), (histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, (min(conditions_2.allnull)), (max(conditions_2.temperature)), ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), (avg(conditions_2.humidity)), (round(stddev((conditions_2.humidity)::integer), 5)), (bit_and(conditions_2.bit_int)), (bit_or(conditions_2.bit_int)), (bool_and(conditions_2.good_life)), (every((conditions_2.temperature > '0'::double precision))), (bool_or(conditions_2.good_life)), (count(*)), (count(conditions_2.temperature)), (count(conditions_2.allnull)), (round((corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round((regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision))::numeric, 5)), (round(stddev((conditions_2.temperature)::integer), 5)), (round(stddev_pop((conditions_2.temperature)::integer), 5)), (round(stddev_samp((conditions_2.temperature)::integer), 5)), (round(variance((conditions_2.temperature)::integer), 5)), (round(var_pop((conditions_2.temperature)::integer), 5)), (round(var_samp((conditions_2.temperature)::integer), 5)), (last(conditions_2.temperature, conditions_2.timec)), (histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev(humidity::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > 0::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round(corr(temperature::integer, humidity::integer)::numeric, 5), round(covar_pop(temperature::integer, humidity::integer)::numeric, 5), round(covar_samp(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgx(temperature::integer, humidity::integer)::numeric, 5), round(regr_avgy(temperature::integer, humidity::integer)::numeric, 5), round(regr_count(temperature::integer, humidity::integer)::numeric, 5), round(regr_intercept(temperature::integer, humidity::integer)::numeric, 5), round(regr_r2(temperature::integer, humidity::integer)::numeric, 5), round(regr_slope(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxx(temperature::integer, humidity::integer)::numeric, 5), round(regr_sxy(temperature::integer, humidity::integer)::numeric, 5), round(regr_syy(temperature::integer, humidity::integer)::numeric, 5), round(stddev(temperature::integer), 5), round(stddev_pop(temperature::integer), 5), round(stddev_samp(temperature::integer), 5), round(variance(temperature::integer), 5), round(var_pop(temperature::integer), 5), round(var_samp(temperature::integer), 5), public.last(temperature, timec), public.histogram(temperature, 0::double precision, 100::double precision, 1), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 35 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Result - Output: conditions.location, conditions.timec, conditions.highlow - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.highlow, conditions.timec - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, last(conditions_1.highlow, conditions_1.timec), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Result - Output: conditions_1.location, conditions_1.timec, conditions_1.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.highlow, conditions_1.timec - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, last(conditions_2.highlow, conditions_2.timec), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Result - Output: conditions_2.location, conditions_2.timec, conditions_2.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.highlow, conditions_2.timec - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(32 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Merge Append - Sort Key: conditions.location, conditions.timec - -> GroupAggregate - Output: conditions.location, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.location, conditions.timec - -> Result - Output: conditions.location, conditions.timec, conditions.allnull, conditions.temperature, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.location, conditions.allnull, conditions.temperature, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow, conditions.timec - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_1.location, min(conditions_1.allnull), max(conditions_1.temperature), (sum(conditions_1.temperature) + sum(conditions_1.humidity)), avg(conditions_1.humidity), round(stddev((conditions_1.humidity)::integer), 5), bit_and(conditions_1.bit_int), bit_or(conditions_1.bit_int), bool_and(conditions_1.good_life), every((conditions_1.temperature > '0'::double precision)), bool_or(conditions_1.good_life), first(conditions_1.highlow, conditions_1.timec), conditions_1.timec - Group Key: conditions_1.location, conditions_1.timec - -> Result - Output: conditions_1.location, conditions_1.timec, conditions_1.allnull, conditions_1.temperature, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.location, conditions_1.allnull, conditions_1.temperature, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow, conditions_1.timec - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> GroupAggregate - Output: conditions_2.location, min(conditions_2.allnull), max(conditions_2.temperature), (sum(conditions_2.temperature) + sum(conditions_2.humidity)), avg(conditions_2.humidity), round(stddev((conditions_2.humidity)::integer), 5), bit_and(conditions_2.bit_int), bit_or(conditions_2.bit_int), bool_and(conditions_2.good_life), every((conditions_2.temperature > '0'::double precision)), bool_or(conditions_2.good_life), first(conditions_2.highlow, conditions_2.timec), conditions_2.timec - Group Key: conditions_2.location, conditions_2.timec - -> Result - Output: conditions_2.location, conditions_2.timec, conditions_2.allnull, conditions_2.temperature, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.location, conditions_2.allnull, conditions_2.temperature, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow, conditions_2.timec - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, location, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(32 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: location, ((sum(temperature) + sum(humidity))), timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, ((sum(conditions.temperature) + sum(conditions.humidity))), conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, ((sum(conditions_1.temperature) + sum(conditions_1.humidity))), conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, ((sum(conditions_2.temperature) + sum(conditions_2.humidity))), conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, (sum(temperature) + sum(humidity)), timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 3 ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: location, timec - -> Merge Append - Sort Key: conditions.location, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.location, conditions.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.location, conditions_1.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.location, conditions_2.timec - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT location, timec FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2 HAVING ((avg(temperature) > 20::double precision)) ORDER BY location ASC NULLS LAST, timec ASC NULLS LAST -(22 rows) - -\set GROUPING 'region, temperature' -\ir 'include/aggregate_queries.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. --- This files assumes the existence of some table with definition as seen in the aggregate_table.sql file. --- All of these should be able to be pushed down if enabled -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - count(*) as count_rows, - count(temperature) as count_temp, - count(allnull) as count_zero, - ROUND(CAST(corr(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_pop(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(covar_samp(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_avgy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_count(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_intercept(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_r2(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_slope(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxx(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_sxy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(CAST(regr_syy(CAST(temperature AS INT), CAST(humidity AS INT)) AS NUMERIC), 5), - ROUND(stddev(CAST(temperature AS INT)), 5) as stddev_temp, - ROUND(stddev_pop(CAST(temperature AS INT)), 5), - ROUND(stddev_samp(CAST(temperature AS INT)), 5), - ROUND(variance(CAST(temperature AS INT)), 5), - ROUND(var_pop(CAST(temperature AS INT)), 5), - ROUND(var_samp(CAST(temperature AS INT)), 5), - last(temperature, timec) as last_temp, - histogram(temperature, 0, 100, 1) - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, min(allnull), max(temperature), (sum(temperature) + sum(humidity)), avg(humidity), round(stddev((humidity)::integer), 5), bit_and(bit_int), bit_or(bit_int), bool_and(good_life), every((temperature > '0'::double precision)), bool_or(good_life), count(*), count(temperature), count(allnull), round((corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round((regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision))::numeric, 5), round(stddev((temperature)::integer), 5), round(stddev_pop((temperature)::integer), 5), round(stddev_samp((temperature)::integer), 5), round(variance((temperature)::integer), 5), round(var_pop((temperature)::integer), 5), round(var_samp((temperature)::integer), 5), last(temperature, timec), histogram(temperature, '0'::double precision, '100'::double precision, 1), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL min(allnull)), (PARTIAL max(temperature)), (PARTIAL sum(temperature)), (PARTIAL sum(humidity)), (PARTIAL avg(humidity)), (PARTIAL stddev((humidity)::integer)), (PARTIAL bit_and(bit_int)), (PARTIAL bit_or(bit_int)), (PARTIAL bool_and(good_life)), (PARTIAL every((temperature > '0'::double precision))), (PARTIAL bool_or(good_life)), (PARTIAL count(*)), (PARTIAL count(temperature)), (PARTIAL count(allnull)), (PARTIAL corr(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_pop(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL covar_samp(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_avgy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_count(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_intercept(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_r2(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_slope(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxx(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_sxy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL regr_syy(((temperature)::integer)::double precision, ((humidity)::integer)::double precision)), (PARTIAL stddev((temperature)::integer)), (PARTIAL stddev_pop((temperature)::integer)), (PARTIAL stddev_samp((temperature)::integer)), (PARTIAL variance((temperature)::integer)), (PARTIAL var_pop((temperature)::integer)), (PARTIAL var_samp((temperature)::integer)), (PARTIAL last(temperature, timec)), (PARTIAL histogram(temperature, '0'::double precision, '100'::double precision, 1)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL min(conditions.allnull)), (PARTIAL max(conditions.temperature)), (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)), (PARTIAL avg(conditions.humidity)), (PARTIAL stddev((conditions.humidity)::integer)), (PARTIAL bit_and(conditions.bit_int)), (PARTIAL bit_or(conditions.bit_int)), (PARTIAL bool_and(conditions.good_life)), (PARTIAL every((conditions.temperature > '0'::double precision))), (PARTIAL bool_or(conditions.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions.temperature)), (PARTIAL count(conditions.allnull)), (PARTIAL corr(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions.temperature)::integer)::double precision, ((conditions.humidity)::integer)::double precision)), (PARTIAL stddev((conditions.temperature)::integer)), (PARTIAL stddev_pop((conditions.temperature)::integer)), (PARTIAL stddev_samp((conditions.temperature)::integer)), (PARTIAL variance((conditions.temperature)::integer)), (PARTIAL var_pop((conditions.temperature)::integer)), (PARTIAL var_samp((conditions.temperature)::integer)), (PARTIAL last(conditions.temperature, conditions.timec)), (PARTIAL histogram(conditions.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL min(conditions_1.allnull)), (PARTIAL max(conditions_1.temperature)), (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)), (PARTIAL avg(conditions_1.humidity)), (PARTIAL stddev((conditions_1.humidity)::integer)), (PARTIAL bit_and(conditions_1.bit_int)), (PARTIAL bit_or(conditions_1.bit_int)), (PARTIAL bool_and(conditions_1.good_life)), (PARTIAL every((conditions_1.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_1.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_1.temperature)), (PARTIAL count(conditions_1.allnull)), (PARTIAL corr(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_1.temperature)::integer)::double precision, ((conditions_1.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_1.temperature)::integer)), (PARTIAL stddev_pop((conditions_1.temperature)::integer)), (PARTIAL stddev_samp((conditions_1.temperature)::integer)), (PARTIAL variance((conditions_1.temperature)::integer)), (PARTIAL var_pop((conditions_1.temperature)::integer)), (PARTIAL var_samp((conditions_1.temperature)::integer)), (PARTIAL last(conditions_1.temperature, conditions_1.timec)), (PARTIAL histogram(conditions_1.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL min(conditions_2.allnull)), (PARTIAL max(conditions_2.temperature)), (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)), (PARTIAL avg(conditions_2.humidity)), (PARTIAL stddev((conditions_2.humidity)::integer)), (PARTIAL bit_and(conditions_2.bit_int)), (PARTIAL bit_or(conditions_2.bit_int)), (PARTIAL bool_and(conditions_2.good_life)), (PARTIAL every((conditions_2.temperature > '0'::double precision))), (PARTIAL bool_or(conditions_2.good_life)), (PARTIAL count(*)), (PARTIAL count(conditions_2.temperature)), (PARTIAL count(conditions_2.allnull)), (PARTIAL corr(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_pop(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL covar_samp(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_avgy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_count(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_intercept(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_r2(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_slope(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxx(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_sxy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL regr_syy(((conditions_2.temperature)::integer)::double precision, ((conditions_2.humidity)::integer)::double precision)), (PARTIAL stddev((conditions_2.temperature)::integer)), (PARTIAL stddev_pop((conditions_2.temperature)::integer)), (PARTIAL stddev_samp((conditions_2.temperature)::integer)), (PARTIAL variance((conditions_2.temperature)::integer)), (PARTIAL var_pop((conditions_2.temperature)::integer)), (PARTIAL var_samp((conditions_2.temperature)::integer)), (PARTIAL last(conditions_2.temperature, conditions_2.timec)), (PARTIAL histogram(conditions_2.temperature, '0'::double precision, '100'::double precision, 1)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(min(allnull)), _timescaledb_functions.partialize_agg(max(temperature)), _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)), _timescaledb_functions.partialize_agg(avg(humidity)), _timescaledb_functions.partialize_agg(stddev(humidity::integer)), _timescaledb_functions.partialize_agg(bit_and(bit_int)), _timescaledb_functions.partialize_agg(bit_or(bit_int)), _timescaledb_functions.partialize_agg(bool_and(good_life)), _timescaledb_functions.partialize_agg(every((temperature > 0::double precision))), _timescaledb_functions.partialize_agg(bool_or(good_life)), _timescaledb_functions.partialize_agg(count(*)), _timescaledb_functions.partialize_agg(count(temperature)), _timescaledb_functions.partialize_agg(count(allnull)), _timescaledb_functions.partialize_agg(corr(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_pop(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(covar_samp(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_avgy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_count(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_intercept(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_r2(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_slope(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxx(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_sxy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(regr_syy(temperature::integer, humidity::integer)), _timescaledb_functions.partialize_agg(stddev(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_pop(temperature::integer)), _timescaledb_functions.partialize_agg(stddev_samp(temperature::integer)), _timescaledb_functions.partialize_agg(variance(temperature::integer)), _timescaledb_functions.partialize_agg(var_pop(temperature::integer)), _timescaledb_functions.partialize_agg(var_samp(temperature::integer)), _timescaledb_functions.partialize_agg(public.last(temperature, timec)), _timescaledb_functions.partialize_agg(public.histogram(temperature, 0::double precision, 100::double precision, 1)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates on custom types are not yet pushed down -:PREFIX SELECT :GROUPING, - last(highlow, timec) as last_hl, - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, last(conditions.highlow, conditions.timec), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL last(conditions.highlow, conditions.timec), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Result - Output: conditions.region, conditions.temperature, conditions.timec, conditions.highlow - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.highlow, conditions.timec - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL last(conditions_1.highlow, conditions_1.timec), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Result - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.highlow, conditions_1.timec - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL last(conditions_2.highlow, conditions_2.timec), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Result - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.highlow, conditions_2.timec - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, highlow FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(35 rows) - --- Mix of aggregates that push down and those that don't -:PREFIX SELECT :GROUPING, - min(allnull) as min_allnull, - max(temperature) as max_temp, - sum(temperature)+sum(humidity) as agg_sum_expr, - avg(humidity), - ROUND(stddev(CAST(humidity AS INT)), 5), - bit_and(bit_int), - bit_or(bit_int), - bool_and(good_life), - every(temperature > 0), - bool_or(good_life), - first(highlow, timec) as first_hl - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: conditions.region, conditions.temperature, min(conditions.allnull), max(conditions.temperature), (sum(conditions.temperature) + sum(conditions.humidity)), avg(conditions.humidity), round(stddev((conditions.humidity)::integer), 5), bit_and(conditions.bit_int), bit_or(conditions.bit_int), bool_and(conditions.good_life), every((conditions.temperature > '0'::double precision)), bool_or(conditions.good_life), first(conditions.highlow, conditions.timec), conditions.timec - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Partial GroupAggregate - Output: conditions.region, conditions.temperature, conditions.timec, PARTIAL min(conditions.allnull), PARTIAL max(conditions.temperature), PARTIAL sum(conditions.temperature), PARTIAL sum(conditions.humidity), PARTIAL avg(conditions.humidity), PARTIAL stddev((conditions.humidity)::integer), PARTIAL bit_and(conditions.bit_int), PARTIAL bit_or(conditions.bit_int), PARTIAL bool_and(conditions.good_life), PARTIAL every((conditions.temperature > '0'::double precision)), PARTIAL bool_or(conditions.good_life), PARTIAL first(conditions.highlow, conditions.timec) - Group Key: conditions.region, conditions.temperature, conditions.timec - -> Result - Output: conditions.region, conditions.temperature, conditions.timec, conditions.allnull, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow - -> Custom Scan (DataNodeScan) on public.conditions - Output: conditions.region, conditions.temperature, conditions.allnull, conditions.humidity, conditions.bit_int, conditions.good_life, conditions.highlow, conditions.timec - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, PARTIAL min(conditions_1.allnull), PARTIAL max(conditions_1.temperature), PARTIAL sum(conditions_1.temperature), PARTIAL sum(conditions_1.humidity), PARTIAL avg(conditions_1.humidity), PARTIAL stddev((conditions_1.humidity)::integer), PARTIAL bit_and(conditions_1.bit_int), PARTIAL bit_or(conditions_1.bit_int), PARTIAL bool_and(conditions_1.good_life), PARTIAL every((conditions_1.temperature > '0'::double precision)), PARTIAL bool_or(conditions_1.good_life), PARTIAL first(conditions_1.highlow, conditions_1.timec) - Group Key: conditions_1.region, conditions_1.temperature, conditions_1.timec - -> Result - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, conditions_1.allnull, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_1 - Output: conditions_1.region, conditions_1.temperature, conditions_1.allnull, conditions_1.humidity, conditions_1.bit_int, conditions_1.good_life, conditions_1.highlow, conditions_1.timec - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Partial GroupAggregate - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, PARTIAL min(conditions_2.allnull), PARTIAL max(conditions_2.temperature), PARTIAL sum(conditions_2.temperature), PARTIAL sum(conditions_2.humidity), PARTIAL avg(conditions_2.humidity), PARTIAL stddev((conditions_2.humidity)::integer), PARTIAL bit_and(conditions_2.bit_int), PARTIAL bit_or(conditions_2.bit_int), PARTIAL bool_and(conditions_2.good_life), PARTIAL every((conditions_2.temperature > '0'::double precision)), PARTIAL bool_or(conditions_2.good_life), PARTIAL first(conditions_2.highlow, conditions_2.timec) - Group Key: conditions_2.region, conditions_2.temperature, conditions_2.timec - -> Result - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, conditions_2.allnull, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow - -> Custom Scan (DataNodeScan) on public.conditions conditions_2 - Output: conditions_2.region, conditions_2.temperature, conditions_2.allnull, conditions_2.humidity, conditions_2.bit_int, conditions_2.good_life, conditions_2.highlow, conditions_2.timec - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT timec, region, temperature, humidity, allnull, highlow, bit_int, good_life FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(35 rows) - --- Aggregates nested in expressions and no top-level aggregate #3672 -:PREFIX SELECT :GROUPING, - sum(temperature)+sum(humidity) as agg_sum_expr - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, (sum(temperature) + sum(humidity)), timec - Group Key: region, temperature, timec - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL sum(temperature)), (PARTIAL sum(humidity)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL sum(conditions.temperature)), (PARTIAL sum(conditions.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL sum(conditions_1.temperature)), (PARTIAL sum(conditions_1.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL sum(conditions_2.temperature)), (PARTIAL sum(conditions_2.humidity)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(sum(temperature)), _timescaledb_functions.partialize_agg(sum(humidity)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(25 rows) - --- Aggregates with no aggregate reference in targetlist #3664 -:PREFIX SELECT :GROUPING - FROM :TEST_TABLE - GROUP BY :GROUPING, timec - HAVING avg(temperature) > 20 - ORDER BY :GROUPING, timec; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: region, temperature, timec - Group Key: region, temperature, timec - Filter: (avg(temperature) > '20'::double precision) - -> Custom Scan (AsyncAppend) - Output: region, temperature, timec, (PARTIAL avg(temperature)) - -> Merge Append - Sort Key: conditions.region, conditions.temperature, conditions.timec - -> Custom Scan (DataNodeScan) - Output: conditions.region, conditions.temperature, conditions.timec, (PARTIAL avg(conditions.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_1.region, conditions_1.temperature, conditions_1.timec, (PARTIAL avg(conditions_1.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_2 - Chunks: _dist_hyper_1_9_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_12_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: conditions_2.region, conditions_2.temperature, conditions_2.timec, (PARTIAL avg(conditions_2.temperature)) - Relations: Aggregate on (public.conditions) - Data node: db_dist_partial_agg_3 - Chunks: _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk - Remote SQL: SELECT region, temperature, timec, _timescaledb_functions.partialize_agg(avg(temperature)) FROM public.conditions WHERE _timescaledb_functions.chunks_in(public.conditions.*, ARRAY[1, 2, 3, 4]) GROUP BY 1, 2, 3 ORDER BY region ASC NULLS LAST, temperature ASC NULLS LAST, timec ASC NULLS LAST -(26 rows) - --- Full aggregate pushdown correctness check, compare location grouped query results with partionwise aggregates on and off -\set GROUPING 'location' -SELECT format('%s/results/dist_agg_loc_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST1", - format('%s/results/dist_agg_loc_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL1" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL1', :'RESULTS_TEST1') as "DIFF_CMD1" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD1 --- Partial aggregate pushdown correctness check, compare region grouped query results with partionwise aggregates on and off -\set GROUPING 'region' -SELECT format('%s/results/dist_agg_region_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST2", - format('%s/results/dist_agg_region_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL2" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL2', :'RESULTS_TEST2') as "DIFF_CMD2" -\gset ---generate the results into two different files -\set ECHO errors -:DIFF_CMD2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_policy.out b/tsl/test/expected/dist_policy.out deleted file mode 100644 index 4bcfd8b7cf1..00000000000 --- a/tsl/test/expected/dist_policy.out +++ /dev/null @@ -1,303 +0,0 @@ --- 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. --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------+------------------+--------------+------------------+------------------- - db_dist_policy_1 | db_dist_policy_1 | t | t | t - db_dist_policy_2 | db_dist_policy_2 | t | t | t - db_dist_policy_3 | db_dist_policy_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Create a fake clock that we can use below and make sure that it is --- defined on the data nodes as well. -CREATE TABLE time_table (time BIGINT); -INSERT INTO time_table VALUES (1); -CREATE OR REPLACE FUNCTION dummy_now() -RETURNS BIGINT -LANGUAGE SQL -STABLE AS 'SELECT time FROM time_table'; -GRANT ALL ON TABLE time_table TO PUBLIC; -SELECT * FROM test.remote_exec(NULL, $$ - CREATE TABLE time_table (time BIGINT); - INSERT INTO time_table VALUES (1); - CREATE OR REPLACE FUNCTION dummy_now() - RETURNS BIGINT - LANGUAGE SQL - STABLE AS 'SELECT time FROM time_table'; - GRANT ALL ON TABLE time_table TO PUBLIC; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_policy_1]: - CREATE TABLE time_table (time BIGINT) -NOTICE: [db_dist_policy_1]: - INSERT INTO time_table VALUES (1) -NOTICE: [db_dist_policy_1]: - CREATE OR REPLACE FUNCTION dummy_now() - RETURNS BIGINT - LANGUAGE SQL - STABLE AS 'SELECT time FROM time_table' -NOTICE: [db_dist_policy_1]: - GRANT ALL ON TABLE time_table TO PUBLIC -NOTICE: [db_dist_policy_2]: - CREATE TABLE time_table (time BIGINT) -NOTICE: [db_dist_policy_2]: - INSERT INTO time_table VALUES (1) -NOTICE: [db_dist_policy_2]: - CREATE OR REPLACE FUNCTION dummy_now() - RETURNS BIGINT - LANGUAGE SQL - STABLE AS 'SELECT time FROM time_table' -NOTICE: [db_dist_policy_2]: - GRANT ALL ON TABLE time_table TO PUBLIC -NOTICE: [db_dist_policy_3]: - CREATE TABLE time_table (time BIGINT) -NOTICE: [db_dist_policy_3]: - INSERT INTO time_table VALUES (1) -NOTICE: [db_dist_policy_3]: - CREATE OR REPLACE FUNCTION dummy_now() - RETURNS BIGINT - LANGUAGE SQL - STABLE AS 'SELECT time FROM time_table' -NOTICE: [db_dist_policy_3]: - GRANT ALL ON TABLE time_table TO PUBLIC - remote_exec -------------- - -(1 row) - -SET ROLE :ROLE_1; -CREATE TABLE conditions( - time BIGINT NOT NULL, - device INT, - value FLOAT -); -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3, - chunk_time_interval => 5); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | conditions | t -(1 row) - -SELECT set_integer_now_func('conditions', 'dummy_now'); - set_integer_now_func ----------------------- - -(1 row) - -INSERT INTO conditions -SELECT time, device, random()*80 -FROM generate_series(1, 40) AS time, - generate_series(1,3) AS device -ORDER BY time, device; -SELECT add_retention_policy('conditions', 5, true) as retention_job_id \gset --- Now simulate drop_chunks running automatically by calling it --- explicitly. Show chunks before and after. -SELECT show_chunks('conditions'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk - _timescaledb_internal._dist_hyper_1_6_chunk - _timescaledb_internal._dist_hyper_1_7_chunk - _timescaledb_internal._dist_hyper_1_8_chunk - _timescaledb_internal._dist_hyper_1_9_chunk - _timescaledb_internal._dist_hyper_1_10_chunk - _timescaledb_internal._dist_hyper_1_11_chunk - _timescaledb_internal._dist_hyper_1_12_chunk - _timescaledb_internal._dist_hyper_1_13_chunk - _timescaledb_internal._dist_hyper_1_14_chunk - _timescaledb_internal._dist_hyper_1_15_chunk - _timescaledb_internal._dist_hyper_1_16_chunk - _timescaledb_internal._dist_hyper_1_17_chunk - _timescaledb_internal._dist_hyper_1_18_chunk - _timescaledb_internal._dist_hyper_1_19_chunk - _timescaledb_internal._dist_hyper_1_20_chunk - _timescaledb_internal._dist_hyper_1_21_chunk - _timescaledb_internal._dist_hyper_1_22_chunk - _timescaledb_internal._dist_hyper_1_23_chunk - _timescaledb_internal._dist_hyper_1_24_chunk - _timescaledb_internal._dist_hyper_1_25_chunk - _timescaledb_internal._dist_hyper_1_26_chunk - _timescaledb_internal._dist_hyper_1_27_chunk -(27 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('conditions'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_policy_1]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_4_chunk -_timescaledb_internal._dist_hyper_1_7_chunk -_timescaledb_internal._dist_hyper_1_10_chunk -_timescaledb_internal._dist_hyper_1_13_chunk -_timescaledb_internal._dist_hyper_1_16_chunk -_timescaledb_internal._dist_hyper_1_19_chunk -_timescaledb_internal._dist_hyper_1_22_chunk -_timescaledb_internal._dist_hyper_1_25_chunk -(9 rows) - - -NOTICE: [db_dist_policy_2]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_5_chunk -_timescaledb_internal._dist_hyper_1_8_chunk -_timescaledb_internal._dist_hyper_1_11_chunk -_timescaledb_internal._dist_hyper_1_14_chunk -_timescaledb_internal._dist_hyper_1_17_chunk -_timescaledb_internal._dist_hyper_1_20_chunk -_timescaledb_internal._dist_hyper_1_23_chunk -_timescaledb_internal._dist_hyper_1_26_chunk -(9 rows) - - -NOTICE: [db_dist_policy_3]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_6_chunk -_timescaledb_internal._dist_hyper_1_9_chunk -_timescaledb_internal._dist_hyper_1_12_chunk -_timescaledb_internal._dist_hyper_1_15_chunk -_timescaledb_internal._dist_hyper_1_18_chunk -_timescaledb_internal._dist_hyper_1_21_chunk -_timescaledb_internal._dist_hyper_1_24_chunk -_timescaledb_internal._dist_hyper_1_27_chunk -(9 rows) - - - remote_exec -------------- - -(1 row) - -UPDATE time_table SET time = 20; -SELECT * FROM test.remote_exec(NULL, $$ UPDATE time_table SET time = 20; $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_policy_1]: UPDATE time_table SET time = 20 -NOTICE: [db_dist_policy_2]: UPDATE time_table SET time = 20 -NOTICE: [db_dist_policy_3]: UPDATE time_table SET time = 20 - remote_exec -------------- - -(1 row) - -CALL run_job(:retention_job_id); -SELECT show_chunks('conditions'); - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_10_chunk - _timescaledb_internal._dist_hyper_1_11_chunk - _timescaledb_internal._dist_hyper_1_12_chunk - _timescaledb_internal._dist_hyper_1_13_chunk - _timescaledb_internal._dist_hyper_1_14_chunk - _timescaledb_internal._dist_hyper_1_15_chunk - _timescaledb_internal._dist_hyper_1_16_chunk - _timescaledb_internal._dist_hyper_1_17_chunk - _timescaledb_internal._dist_hyper_1_18_chunk - _timescaledb_internal._dist_hyper_1_19_chunk - _timescaledb_internal._dist_hyper_1_20_chunk - _timescaledb_internal._dist_hyper_1_21_chunk - _timescaledb_internal._dist_hyper_1_22_chunk - _timescaledb_internal._dist_hyper_1_23_chunk - _timescaledb_internal._dist_hyper_1_24_chunk - _timescaledb_internal._dist_hyper_1_25_chunk - _timescaledb_internal._dist_hyper_1_26_chunk - _timescaledb_internal._dist_hyper_1_27_chunk -(18 rows) - -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('conditions'); $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_policy_1]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_1]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_10_chunk -_timescaledb_internal._dist_hyper_1_13_chunk -_timescaledb_internal._dist_hyper_1_16_chunk -_timescaledb_internal._dist_hyper_1_19_chunk -_timescaledb_internal._dist_hyper_1_22_chunk -_timescaledb_internal._dist_hyper_1_25_chunk -(6 rows) - - -NOTICE: [db_dist_policy_2]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_2]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_11_chunk -_timescaledb_internal._dist_hyper_1_14_chunk -_timescaledb_internal._dist_hyper_1_17_chunk -_timescaledb_internal._dist_hyper_1_20_chunk -_timescaledb_internal._dist_hyper_1_23_chunk -_timescaledb_internal._dist_hyper_1_26_chunk -(6 rows) - - -NOTICE: [db_dist_policy_3]: SELECT show_chunks('conditions') -NOTICE: [db_dist_policy_3]: -show_chunks --------------------------------------------- -_timescaledb_internal._dist_hyper_1_12_chunk -_timescaledb_internal._dist_hyper_1_15_chunk -_timescaledb_internal._dist_hyper_1_18_chunk -_timescaledb_internal._dist_hyper_1_21_chunk -_timescaledb_internal._dist_hyper_1_24_chunk -_timescaledb_internal._dist_hyper_1_27_chunk -(6 rows) - - - remote_exec -------------- - -(1 row) - -SELECT remove_retention_policy('conditions'); - remove_retention_policy -------------------------- - -(1 row) - --- Check that we can insert into the table without the retention --- policy and not get an error. This will be a problem if the policy --- did not propagate drop_chunks to data nodes. -INSERT INTO conditions -SELECT time, device, random()*80 -FROM generate_series(1,10) AS time, - generate_series(1,3) AS device; --- Make sure reorder policy is blocked for distributed hypertable -\set ON_ERROR_STOP 0 -SELECT add_reorder_policy('conditions', 'conditions_time_idx'); -ERROR: reorder policies not supported on a distributed hypertables -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_query-13.out b/tsl/test/expected/dist_query-13.out deleted file mode 100644 index 88f82b1f5ae..00000000000 --- a/tsl/test/expected/dist_query-13.out +++ /dev/null @@ -1,5939 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set TEST_BASE_NAME dist_query --- Run -SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') AS "TEST_LOAD_NAME", - format('include/%s_run.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME", - format('%s/results/%s_results_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REFERENCE", - format('%s/results/%s_results_repartitioning_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_REFERENCE", - format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_OPTIMIZED", - format('%s/results/%s_results_repartitioning_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_OPTIMIZED", - format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_UNOPTIMIZED", - format('%s/results/%s_results_1dim.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_1DIM" -\gset -SELECT format('\! diff %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_UNOPT", - format('\! diff %s %s', :'TEST_RESULTS_OPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_OPT", - format('\! diff %s %s', :'TEST_RESULTS_REPART_OPTIMIZED', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_REPART", - format('\! diff %s %s', :'TEST_RESULTS_1DIM', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_1DIM" -\gset --- Use a small fetch size to make sure that result are fetched across --- multiple fetches. ---ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '500'); -SET client_min_messages TO notice; --- Load the data -\ir :TEST_LOAD_NAME --- 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. -\ir debugsupport.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. -CREATE OR REPLACE FUNCTION test.tsl_override_current_timestamptz(new_value TIMESTAMPTZ) -RETURNS VOID AS :TSL_MODULE_PATHNAME, 'ts_test_override_current_timestamptz' LANGUAGE C VOLATILE; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_query_1 | db_dist_query_1 | t | t | t - db_dist_query_2 | db_dist_query_2 | t | t | t - db_dist_query_3 | db_dist_query_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Create a "normal" PG table as reference, one two-dimensional --- distributed hypertable, and a one-dimensional distributed --- hypertable -CREATE TABLE reference (time timestamptz NOT NULL, device int, location int, temp float); -CREATE TABLE hyper (LIKE reference); -CREATE TABLE hyper1d (LIKE reference); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours'); -psql:include/dist_query_load.sql:30: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,hyper,t) -(1 row) - -SELECT create_distributed_hypertable('hyper1d', 'time', chunk_time_interval => interval '36 hours'); -psql:include/dist_query_load.sql:32: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,hyper1d,t) -(1 row) - -SELECT setseed(1); - setseed ---------- - -(1 row) - -INSERT INTO reference -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, (random() * 20)::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-04'::timestamptz, '1 minute') as t; --- Insert the same data into the hypertable but repartition the data --- set so that we can test the "safeness" of some push-downs across --- the repartitioning boundary. -INSERT INTO hyper -SELECT * FROM reference -WHERE time < '2019-01-02 05:10'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 2); -psql:include/dist_query_load.sql:47: WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-02 05:10'::timestamptz -AND time < '2019-01-03 01:22'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 5); - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-03 01:22'::timestamptz -ORDER BY time; -INSERT INTO hyper1d -SELECT * FROM reference ORDER BY time; -SELECT d.hypertable_id, d.id, ds.range_start, ds.range_end -FROM _timescaledb_catalog.dimension d, _timescaledb_catalog.dimension_slice ds -WHERE num_slices IS NOT NULL -AND d.id = ds.dimension_id -ORDER BY 1, 2, 3, 4; - hypertable_id | id | range_start | range_end ----------------+----+----------------------+--------------------- - 1 | 2 | -9223372036854775808 | 429496729 - 1 | 2 | -9223372036854775808 | 715827882 - 1 | 2 | -9223372036854775808 | 1073741823 - 1 | 2 | 429496729 | 858993458 - 1 | 2 | 715827882 | 1431655764 - 1 | 2 | 858993458 | 1288490187 - 1 | 2 | 1073741823 | 9223372036854775807 - 1 | 2 | 1288490187 | 1717986916 - 1 | 2 | 1431655764 | 9223372036854775807 - 1 | 2 | 1717986916 | 9223372036854775807 -(10 rows) - --- Set the max time we can query without hitting the repartitioned --- chunks. Note that this is before the given repartitioning time --- above because chunk boundaries do not align exactly with the given --- timestamp -\set REPARTITIONED_TIME_RANGE 'time >= ''2019-01-01''' -\set CLEAN_PARTITIONING_TIME_RANGE 'time BETWEEN ''2019-01-01'' AND ''2019-01-01 15:00''' --- Custom agg func for push down tests -CREATE AGGREGATE custom_sum(int4) ( - SFUNC = int4_sum, - STYPE = int8 -); --- Set seed on all data nodes for ANALYZE to sample consistently -CALL distributed_exec($$ SELECT setseed(1); $$); -ANALYZE reference; -ANALYZE hyper; -ANALYZE hyper1d; -SELECT hypertable_schema, hypertable_name, num_dimensions, num_chunks -FROM timescaledb_information.hypertables -ORDER BY 1,2; - hypertable_schema | hypertable_name | num_dimensions | num_chunks --------------------+-----------------+----------------+------------ - public | hyper | 2 | 18 - public | hyper1d | 1 | 3 -(2 rows) - -SELECT count(*) FROM hyper; - count -------- - 4321 -(1 row) - -SELECT count(*) FROM hyper WHERE :CLEAN_PARTITIONING_TIME_RANGE; - count -------- - 901 -(1 row) - -SET enable_partitionwise_aggregate = ON; -\set ECHO errors - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(21 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) -(21 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(21 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Append - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, avg(hyper_1.temp), sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, avg(hyper_2.temp), sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp) - Group Key: hyper_1."time", hyper_1.device - Filter: ((avg(hyper_1.temp) * (custom_sum(hyper_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp) - Group Key: hyper_2."time", hyper_2.device - Filter: ((avg(hyper_2.temp) * (custom_sum(hyper_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp), custom_sum(hyper_1.device) - Group Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp), custom_sum(hyper_2.device) - Group Key: hyper_2."time", hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 0 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT greatest(random(), 10.0) - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(25 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(22 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE AND device = 1 -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Sort - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - One-Time Filter: false -(9 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 -(6 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY location ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(8 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(8 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device - -> Nested Loop - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, hyper.temp - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp, time_bucket('@ 1 min'::interval, hyper."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - Filter: (top_n.device = 1) - -> Limit - Output: hyper_1.device, (avg(hyper_1.temp)) - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY avg(temp) DESC NULLS FIRST -(23 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: LIMIT 10 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", (avg(temp)) - -> Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), (avg(temp)) - -> Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(24 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.location, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)), (sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision))) - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)), (custom_sum(hyper.device)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)), (PARTIAL max(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)), (PARTIAL max(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)), (PARTIAL max(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Sort - Output: device, (PARTIAL avg(temp)) - Sort Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.location - -> Partial GroupAggregate - Output: hyper.location, PARTIAL avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_1.location, PARTIAL avg(hyper_1.temp) - Group Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_2.location, PARTIAL avg(hyper_2.temp) - Group Key: hyper_2.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, PARTIAL avg(hyper.temp), PARTIAL sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, PARTIAL avg(hyper_1.temp), PARTIAL sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, PARTIAL avg(hyper_2.temp), PARTIAL sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(29 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper_4.device - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (PARTIAL avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (PARTIAL avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (PARTIAL avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(60 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", (avg(temp)) - -> Merge Append - Sort Key: hyper1d."time" - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(22 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Sort - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - Sort Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(27 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)), (PARTIAL max(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)), (PARTIAL max(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)), (PARTIAL max(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(28 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d.location - -> Partial GroupAggregate - Output: hyper1d.location, PARTIAL avg(hyper1d.temp) - Group Key: hyper1d.location - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d.location, hyper1d.temp - Filter: ((hyper1d.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_1.location, PARTIAL avg(hyper1d_1.temp) - Group Key: hyper1d_1.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.location, hyper1d_1.temp - Filter: ((hyper1d_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_2.location, PARTIAL avg(hyper1d_2.temp) - Group Key: hyper1d_2.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.location, hyper1d_2.temp - Filter: ((hyper1d_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp), sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, PARTIAL avg(hyper1d.temp), PARTIAL sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, PARTIAL avg(hyper1d_1.temp), PARTIAL sum((hyper1d_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, PARTIAL avg(hyper1d_2.temp), PARTIAL sum((hyper1d_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(29 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) - Group Key: hyper1d."time", hyper1d.device - Filter: ((avg(hyper1d.temp) * (custom_sum(hyper1d.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp) - Group Key: hyper1d_1."time", hyper1d_1.device - Filter: ((avg(hyper1d_1.temp) * (custom_sum(hyper1d_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp) - Group Key: hyper1d_2."time", hyper1d_2.device - Filter: ((avg(hyper1d_2.temp) * (custom_sum(hyper1d_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp), custom_sum(hyper1d.device) - Group Key: hyper1d."time", hyper1d.device - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp), custom_sum(hyper1d_1.device) - Group Key: hyper1d_1."time", hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp), custom_sum(hyper1d_2.device) - Group Key: hyper1d_2."time", hyper1d_2.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 0 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT greatest(random(), 10.0) - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper1d - -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp) OVER (?)) - -> WindowAgg - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time", hyper1d.temp - -> Merge Append - Sort Key: hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time", hyper1d_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time", hyper1d_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time", hyper1d_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device, hyper1d_1."time" - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper1d - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper1d INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - Inner Unique: true - Join Filter: (hyper1d.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device, hyper1d.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper1d_1."time")), hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp, time_bucket('@ 1 min'::interval, hyper1d_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp, time_bucket('@ 1 min'::interval, hyper1d_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device, hyper1d_3.temp, time_bucket('@ 1 min'::interval, hyper1d_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d_4.device - -> Custom Scan (DataNodeScan) - Output: hyper1d_4.device, (PARTIAL avg(hyper1d_4.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_5.device, (PARTIAL avg(hyper1d_5.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_6.device, (PARTIAL avg(hyper1d_6.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(60 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -:DIFF_CMD_UNOPT -:DIFF_CMD_OPT -:DIFF_CMD_REPART -:DIFF_CMD_1DIM -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_query-14.out b/tsl/test/expected/dist_query-14.out deleted file mode 100644 index 88f82b1f5ae..00000000000 --- a/tsl/test/expected/dist_query-14.out +++ /dev/null @@ -1,5939 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set TEST_BASE_NAME dist_query --- Run -SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') AS "TEST_LOAD_NAME", - format('include/%s_run.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME", - format('%s/results/%s_results_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REFERENCE", - format('%s/results/%s_results_repartitioning_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_REFERENCE", - format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_OPTIMIZED", - format('%s/results/%s_results_repartitioning_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_OPTIMIZED", - format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_UNOPTIMIZED", - format('%s/results/%s_results_1dim.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_1DIM" -\gset -SELECT format('\! diff %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_UNOPT", - format('\! diff %s %s', :'TEST_RESULTS_OPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_OPT", - format('\! diff %s %s', :'TEST_RESULTS_REPART_OPTIMIZED', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_REPART", - format('\! diff %s %s', :'TEST_RESULTS_1DIM', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_1DIM" -\gset --- Use a small fetch size to make sure that result are fetched across --- multiple fetches. ---ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '500'); -SET client_min_messages TO notice; --- Load the data -\ir :TEST_LOAD_NAME --- 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. -\ir debugsupport.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. -CREATE OR REPLACE FUNCTION test.tsl_override_current_timestamptz(new_value TIMESTAMPTZ) -RETURNS VOID AS :TSL_MODULE_PATHNAME, 'ts_test_override_current_timestamptz' LANGUAGE C VOLATILE; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_query_1 | db_dist_query_1 | t | t | t - db_dist_query_2 | db_dist_query_2 | t | t | t - db_dist_query_3 | db_dist_query_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Create a "normal" PG table as reference, one two-dimensional --- distributed hypertable, and a one-dimensional distributed --- hypertable -CREATE TABLE reference (time timestamptz NOT NULL, device int, location int, temp float); -CREATE TABLE hyper (LIKE reference); -CREATE TABLE hyper1d (LIKE reference); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours'); -psql:include/dist_query_load.sql:30: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,hyper,t) -(1 row) - -SELECT create_distributed_hypertable('hyper1d', 'time', chunk_time_interval => interval '36 hours'); -psql:include/dist_query_load.sql:32: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,hyper1d,t) -(1 row) - -SELECT setseed(1); - setseed ---------- - -(1 row) - -INSERT INTO reference -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, (random() * 20)::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-04'::timestamptz, '1 minute') as t; --- Insert the same data into the hypertable but repartition the data --- set so that we can test the "safeness" of some push-downs across --- the repartitioning boundary. -INSERT INTO hyper -SELECT * FROM reference -WHERE time < '2019-01-02 05:10'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 2); -psql:include/dist_query_load.sql:47: WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-02 05:10'::timestamptz -AND time < '2019-01-03 01:22'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 5); - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-03 01:22'::timestamptz -ORDER BY time; -INSERT INTO hyper1d -SELECT * FROM reference ORDER BY time; -SELECT d.hypertable_id, d.id, ds.range_start, ds.range_end -FROM _timescaledb_catalog.dimension d, _timescaledb_catalog.dimension_slice ds -WHERE num_slices IS NOT NULL -AND d.id = ds.dimension_id -ORDER BY 1, 2, 3, 4; - hypertable_id | id | range_start | range_end ----------------+----+----------------------+--------------------- - 1 | 2 | -9223372036854775808 | 429496729 - 1 | 2 | -9223372036854775808 | 715827882 - 1 | 2 | -9223372036854775808 | 1073741823 - 1 | 2 | 429496729 | 858993458 - 1 | 2 | 715827882 | 1431655764 - 1 | 2 | 858993458 | 1288490187 - 1 | 2 | 1073741823 | 9223372036854775807 - 1 | 2 | 1288490187 | 1717986916 - 1 | 2 | 1431655764 | 9223372036854775807 - 1 | 2 | 1717986916 | 9223372036854775807 -(10 rows) - --- Set the max time we can query without hitting the repartitioned --- chunks. Note that this is before the given repartitioning time --- above because chunk boundaries do not align exactly with the given --- timestamp -\set REPARTITIONED_TIME_RANGE 'time >= ''2019-01-01''' -\set CLEAN_PARTITIONING_TIME_RANGE 'time BETWEEN ''2019-01-01'' AND ''2019-01-01 15:00''' --- Custom agg func for push down tests -CREATE AGGREGATE custom_sum(int4) ( - SFUNC = int4_sum, - STYPE = int8 -); --- Set seed on all data nodes for ANALYZE to sample consistently -CALL distributed_exec($$ SELECT setseed(1); $$); -ANALYZE reference; -ANALYZE hyper; -ANALYZE hyper1d; -SELECT hypertable_schema, hypertable_name, num_dimensions, num_chunks -FROM timescaledb_information.hypertables -ORDER BY 1,2; - hypertable_schema | hypertable_name | num_dimensions | num_chunks --------------------+-----------------+----------------+------------ - public | hyper | 2 | 18 - public | hyper1d | 1 | 3 -(2 rows) - -SELECT count(*) FROM hyper; - count -------- - 4321 -(1 row) - -SELECT count(*) FROM hyper WHERE :CLEAN_PARTITIONING_TIME_RANGE; - count -------- - 901 -(1 row) - -SET enable_partitionwise_aggregate = ON; -\set ECHO errors - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(21 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) -(21 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(21 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Append - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, avg(hyper_1.temp), sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, avg(hyper_2.temp), sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp) - Group Key: hyper_1."time", hyper_1.device - Filter: ((avg(hyper_1.temp) * (custom_sum(hyper_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp) - Group Key: hyper_2."time", hyper_2.device - Filter: ((avg(hyper_2.temp) * (custom_sum(hyper_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp), custom_sum(hyper_1.device) - Group Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp), custom_sum(hyper_2.device) - Group Key: hyper_2."time", hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 0 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT greatest(random(), 10.0) - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(25 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(22 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE AND device = 1 -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Sort - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - One-Time Filter: false -(9 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 -(6 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY location ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(8 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(8 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device - -> Nested Loop - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, hyper.temp - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp, time_bucket('@ 1 min'::interval, hyper."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - Filter: (top_n.device = 1) - -> Limit - Output: hyper_1.device, (avg(hyper_1.temp)) - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY avg(temp) DESC NULLS FIRST -(23 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: LIMIT 10 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", (avg(temp)) - -> Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), (avg(temp)) - -> Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(24 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.location, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)), (sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision))) - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)), (custom_sum(hyper.device)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(56 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)), (PARTIAL max(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)), (PARTIAL max(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)), (PARTIAL max(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Sort - Output: device, (PARTIAL avg(temp)) - Sort Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.location - -> Partial GroupAggregate - Output: hyper.location, PARTIAL avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_1.location, PARTIAL avg(hyper_1.temp) - Group Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_2.location, PARTIAL avg(hyper_2.temp) - Group Key: hyper_2.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, PARTIAL avg(hyper.temp), PARTIAL sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, PARTIAL avg(hyper_1.temp), PARTIAL sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, PARTIAL avg(hyper_2.temp), PARTIAL sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(29 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time", hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time", hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time", hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(26 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper_4.device - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (PARTIAL avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (PARTIAL avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (PARTIAL avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(60 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", (avg(temp)) - -> Merge Append - Sort Key: hyper1d."time" - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(22 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Sort - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - Sort Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(27 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)), (PARTIAL max(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)), (PARTIAL max(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)), (PARTIAL max(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(28 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d.location - -> Partial GroupAggregate - Output: hyper1d.location, PARTIAL avg(hyper1d.temp) - Group Key: hyper1d.location - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d.location, hyper1d.temp - Filter: ((hyper1d.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_1.location, PARTIAL avg(hyper1d_1.temp) - Group Key: hyper1d_1.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.location, hyper1d_1.temp - Filter: ((hyper1d_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_2.location, PARTIAL avg(hyper1d_2.temp) - Group Key: hyper1d_2.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.location, hyper1d_2.temp - Filter: ((hyper1d_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp), sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, PARTIAL avg(hyper1d.temp), PARTIAL sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, PARTIAL avg(hyper1d_1.temp), PARTIAL sum((hyper1d_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, PARTIAL avg(hyper1d_2.temp), PARTIAL sum((hyper1d_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(29 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) - Group Key: hyper1d."time", hyper1d.device - Filter: ((avg(hyper1d.temp) * (custom_sum(hyper1d.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp) - Group Key: hyper1d_1."time", hyper1d_1.device - Filter: ((avg(hyper1d_1.temp) * (custom_sum(hyper1d_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp) - Group Key: hyper1d_2."time", hyper1d_2.device - Filter: ((avg(hyper1d_2.temp) * (custom_sum(hyper1d_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp), custom_sum(hyper1d.device) - Group Key: hyper1d."time", hyper1d.device - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp), custom_sum(hyper1d_1.device) - Group Key: hyper1d_1."time", hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp), custom_sum(hyper1d_2.device) - Group Key: hyper1d_2."time", hyper1d_2.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 0 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT greatest(random(), 10.0) - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper1d - -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp) OVER (?)) - -> WindowAgg - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time", hyper1d.temp - -> Merge Append - Sort Key: hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time", hyper1d_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time", hyper1d_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time", hyper1d_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device, hyper1d_1."time" - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper1d - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper1d INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - Inner Unique: true - Join Filter: (hyper1d.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device, hyper1d.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper1d_1."time")), hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp, time_bucket('@ 1 min'::interval, hyper1d_1."time") - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp, time_bucket('@ 1 min'::interval, hyper1d_2."time") - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device, hyper1d_3.temp, time_bucket('@ 1 min'::interval, hyper1d_3."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d_4.device - -> Custom Scan (DataNodeScan) - Output: hyper1d_4.device, (PARTIAL avg(hyper1d_4.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_5.device, (PARTIAL avg(hyper1d_5.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_6.device, (PARTIAL avg(hyper1d_6.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(60 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -:DIFF_CMD_UNOPT -:DIFF_CMD_OPT -:DIFF_CMD_REPART -:DIFF_CMD_1DIM -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_query-15.out b/tsl/test/expected/dist_query-15.out deleted file mode 100644 index ec70d3a90fa..00000000000 --- a/tsl/test/expected/dist_query-15.out +++ /dev/null @@ -1,6051 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set TEST_BASE_NAME dist_query --- Run -SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') AS "TEST_LOAD_NAME", - format('include/%s_run.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME", - format('%s/results/%s_results_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REFERENCE", - format('%s/results/%s_results_repartitioning_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_REFERENCE", - format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_OPTIMIZED", - format('%s/results/%s_results_repartitioning_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_OPTIMIZED", - format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_UNOPTIMIZED", - format('%s/results/%s_results_1dim.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_1DIM" -\gset -SELECT format('\! diff %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_UNOPT", - format('\! diff %s %s', :'TEST_RESULTS_OPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_OPT", - format('\! diff %s %s', :'TEST_RESULTS_REPART_OPTIMIZED', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_REPART", - format('\! diff %s %s', :'TEST_RESULTS_1DIM', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_1DIM" -\gset --- Use a small fetch size to make sure that result are fetched across --- multiple fetches. ---ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '500'); -SET client_min_messages TO notice; --- Load the data -\ir :TEST_LOAD_NAME --- 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. -\ir debugsupport.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. -CREATE OR REPLACE FUNCTION test.tsl_override_current_timestamptz(new_value TIMESTAMPTZ) -RETURNS VOID AS :TSL_MODULE_PATHNAME, 'ts_test_override_current_timestamptz' LANGUAGE C VOLATILE; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated -psql:include/dist_query_load.sql:17: WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_query_1 | db_dist_query_1 | t | t | t - db_dist_query_2 | db_dist_query_2 | t | t | t - db_dist_query_3 | db_dist_query_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; --- Create a "normal" PG table as reference, one two-dimensional --- distributed hypertable, and a one-dimensional distributed --- hypertable -CREATE TABLE reference (time timestamptz NOT NULL, device int, location int, temp float); -CREATE TABLE hyper (LIKE reference); -CREATE TABLE hyper1d (LIKE reference); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours'); -psql:include/dist_query_load.sql:30: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,hyper,t) -(1 row) - -SELECT create_distributed_hypertable('hyper1d', 'time', chunk_time_interval => interval '36 hours'); -psql:include/dist_query_load.sql:32: WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,hyper1d,t) -(1 row) - -SELECT setseed(1); - setseed ---------- - -(1 row) - -INSERT INTO reference -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, (random() * 20)::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-04'::timestamptz, '1 minute') as t; --- Insert the same data into the hypertable but repartition the data --- set so that we can test the "safeness" of some push-downs across --- the repartitioning boundary. -INSERT INTO hyper -SELECT * FROM reference -WHERE time < '2019-01-02 05:10'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 2); -psql:include/dist_query_load.sql:47: WARNING: insufficient number of partitions for dimension "device" - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-02 05:10'::timestamptz -AND time < '2019-01-03 01:22'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 5); - set_number_partitions ------------------------ - -(1 row) - -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-03 01:22'::timestamptz -ORDER BY time; -INSERT INTO hyper1d -SELECT * FROM reference ORDER BY time; -SELECT d.hypertable_id, d.id, ds.range_start, ds.range_end -FROM _timescaledb_catalog.dimension d, _timescaledb_catalog.dimension_slice ds -WHERE num_slices IS NOT NULL -AND d.id = ds.dimension_id -ORDER BY 1, 2, 3, 4; - hypertable_id | id | range_start | range_end ----------------+----+----------------------+--------------------- - 1 | 2 | -9223372036854775808 | 429496729 - 1 | 2 | -9223372036854775808 | 715827882 - 1 | 2 | -9223372036854775808 | 1073741823 - 1 | 2 | 429496729 | 858993458 - 1 | 2 | 715827882 | 1431655764 - 1 | 2 | 858993458 | 1288490187 - 1 | 2 | 1073741823 | 9223372036854775807 - 1 | 2 | 1288490187 | 1717986916 - 1 | 2 | 1431655764 | 9223372036854775807 - 1 | 2 | 1717986916 | 9223372036854775807 -(10 rows) - --- Set the max time we can query without hitting the repartitioned --- chunks. Note that this is before the given repartitioning time --- above because chunk boundaries do not align exactly with the given --- timestamp -\set REPARTITIONED_TIME_RANGE 'time >= ''2019-01-01''' -\set CLEAN_PARTITIONING_TIME_RANGE 'time BETWEEN ''2019-01-01'' AND ''2019-01-01 15:00''' --- Custom agg func for push down tests -CREATE AGGREGATE custom_sum(int4) ( - SFUNC = int4_sum, - STYPE = int8 -); --- Set seed on all data nodes for ANALYZE to sample consistently -CALL distributed_exec($$ SELECT setseed(1); $$); -ANALYZE reference; -ANALYZE hyper; -ANALYZE hyper1d; -SELECT hypertable_schema, hypertable_name, num_dimensions, num_chunks -FROM timescaledb_information.hypertables -ORDER BY 1,2; - hypertable_schema | hypertable_name | num_dimensions | num_chunks --------------------+-----------------+----------------+------------ - public | hyper | 2 | 18 - public | hyper1d | 1 | 3 -(2 rows) - -SELECT count(*) FROM hyper; - count -------- - 4321 -(1 row) - -SELECT count(*) FROM hyper WHERE :CLEAN_PARTITIONING_TIME_RANGE; - count -------- - 901 -(1 row) - -SET enable_partitionwise_aggregate = ON; -\set ECHO errors - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(21 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) -(21 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 -(21 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Append - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, avg(hyper_1.temp), sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, avg(hyper_2.temp), sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(31 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp) - Group Key: hyper_1."time", hyper_1.device - Filter: ((avg(hyper_1.temp) * (custom_sum(hyper_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp) - Group Key: hyper_2."time", hyper_2.device - Filter: ((avg(hyper_2.temp) * (custom_sum(hyper_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_1."time", hyper_1.device, avg(hyper_1.temp), custom_sum(hyper_1.device) - Group Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper_2."time", hyper_2.device, avg(hyper_2.temp), custom_sum(hyper_2.device) - Group Key: hyper_2."time", hyper_2.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT 0 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper - -LIMIT greatest(random(), 10.0) - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Result - Output: hyper_1.device, hyper_1."time", hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_2.device, hyper_2."time", hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_3.device, hyper_3."time", hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(29 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper - -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(62 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(25 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(22 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(28 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Result - Output: hyper_1.device, hyper_1."time", hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_2.device, hyper_2."time", hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_3.device, hyper_3."time", hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(32 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(62 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE AND device = 1 -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Sort - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - One-Time Filter: false -(9 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(6 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 -(6 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY location ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(10 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(9 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY "time" ASC NULLS LAST -(8 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST -(6 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Result - Output: hyper_1.device, hyper_1."time", hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_2.device, hyper_2."time", hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_3.device, hyper_3."time", hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(32 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND device = 1 -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device - -> Nested Loop - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, hyper.temp - -> Result - Output: hyper."time", hyper.device, hyper.temp, time_bucket('@ 1 min'::interval, hyper."time") - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - Filter: (top_n.device = 1) - -> Limit - Output: hyper_1.device, (avg(hyper_1.temp)) - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device = 1)) GROUP BY 1 ORDER BY avg(temp) DESC NULLS FIRST -(25 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: LIMIT 10 -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", (avg(temp)) - -> Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper."time" - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), (avg(temp)) - -> Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 HAVING ((avg(temp) > 40::double precision)) AND ((max(temp) < 70::double precision)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(24 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.location, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper.location, avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (AsyncAppend) - Output: hyper.location, hyper.temp - -> Merge Append - Sort Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.location, hyper_3.temp - Filter: ((hyper_3.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (avg(hyper.temp)), (sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision))) - -> GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_3."time"), hyper_3.device, hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp)), (custom_sum(hyper.device)) - -> GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: "time", device, (avg(temp)) - -> Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(24 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Result - Output: hyper_1.device, hyper_1."time", hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_2.device, hyper_2."time", hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_3.device, hyper_3."time", hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(32 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Custom Scan (AsyncAppend) - Output: device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(62 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: "time", avg(temp) - Group Key: "time" - -> Sort - Output: "time", (PARTIAL avg(temp)) - Sort Key: "time" - -> Custom Scan (AsyncAppend) - Output: "time", (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (date_trunc('month'::text, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY date_trunc('month'::text, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 -ORDER BY 1,2 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(25 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, (PARTIAL avg(hyper.temp)), (PARTIAL max(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, (PARTIAL avg(hyper_1.temp)), (PARTIAL max(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, (PARTIAL avg(hyper_2.temp)), (PARTIAL max(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(26 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Sort - Output: device, (PARTIAL avg(temp)) - Sort Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 -(27 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.location - -> Partial GroupAggregate - Output: hyper.location, PARTIAL avg(hyper.temp) - Group Key: hyper.location - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper.location, hyper.temp - Filter: ((hyper.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_1.location, PARTIAL avg(hyper_1.temp) - Group Key: hyper_1.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.location, hyper_1.temp - Filter: ((hyper_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper_2.location, PARTIAL avg(hyper_2.temp) - Group Key: hyper_2.location - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.location, hyper_2.temp - Filter: ((hyper_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT location, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, avg(hyper.temp), sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper."time")), hyper.device, PARTIAL avg(hyper.temp), PARTIAL sum((hyper.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper."time"), hyper.device, hyper.temp - -> Custom Scan (DataNodeScan) on public.hyper - Output: hyper."time", hyper.device, hyper.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_1."time")), hyper_1.device, PARTIAL avg(hyper_1.temp), PARTIAL sum((hyper_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_1."time"), hyper_1.device, hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper_2."time")), hyper_2.device, PARTIAL avg(hyper_2.temp), PARTIAL sum((hyper_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper_2."time"), hyper_2.device, hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(35 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp) - Group Key: hyper."time", hyper.device - Filter: ((avg(hyper.temp) * (custom_sum(hyper.device))::double precision) > '0.8'::double precision) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(23 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: hyper."time", hyper.device, avg(hyper.temp), custom_sum(hyper.device) - Group Key: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Merge Append - Sort Key: hyper."time", hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(22 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 5 -OFFSET 5 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 10 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT 0 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 1 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST LIMIT 2000 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper -ORDER BY 1,2 -LIMIT greatest(random(), 10.0) - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device - -> Merge Append - Sort Key: hyper_1."time", hyper_1.device - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - -> Sort - Output: hyper."time", hyper.device, (avg(hyper.temp) OVER (?)) - Sort Key: hyper."time", hyper.device - -> WindowAgg - Output: hyper."time", hyper.device, avg(hyper.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time", hyper.temp - -> Merge Append - Sort Key: hyper_1.device - -> Result - Output: hyper_1.device, hyper_1."time", hyper_1.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_2.device, hyper_2."time", hyper_2.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper_3.device, hyper_3."time", hyper_3.temp - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST -(32 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper -ORDER BY 1,2 -LIMIT 10 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper.device, hyper."time" - -> Unique - Output: hyper.device, hyper."time" - -> Custom Scan (AsyncAppend) - Output: hyper.device, hyper."time" - -> Merge Append - Sort Key: hyper_1.device, hyper_1."time" - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1.device, hyper_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2.device, hyper_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3.device, hyper_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) - -> Custom Scan (DataNodeScan) on public.hyper t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper."time")), hyper.device, avg(hyper.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper."time"), hyper.device, hyper.temp - Inner Unique: true - Join Filter: (hyper.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper."time", hyper.device, hyper.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper_1."time")), hyper_1.device - -> Result - Output: hyper_1."time", hyper_1.device, hyper_1.temp, time_bucket('@ 1 min'::interval, hyper_1."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_1 - Output: hyper_1."time", hyper_1.device, hyper_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_2."time", hyper_2.device, hyper_2.temp, time_bucket('@ 1 min'::interval, hyper_2."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_2 - Output: hyper_2."time", hyper_2.device, hyper_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper_3."time", hyper_3.device, hyper_3.temp, time_bucket('@ 1 min'::interval, hyper_3."time") - -> Custom Scan (DataNodeScan) on public.hyper hyper_3 - Output: hyper_3."time", hyper_3.device, hyper_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper_4.device - -> Custom Scan (DataNodeScan) - Output: hyper_4.device, (PARTIAL avg(hyper_4.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_5.device, (PARTIAL avg(hyper_5.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_6.device, (PARTIAL avg(hyper_6.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(66 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: EXPLAIN (verbose, costs off) -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - setseed ---------- - -(1 row) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", (avg(temp)) - -> Merge Append - Sort Key: hyper1d."time" - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY "time" ASC NULLS LAST -(22 rows) - - -######### Grouping on time only (partial aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")) - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), (PARTIAL avg(temp)) - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")) - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST -(25 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper."time", hyper.device, (avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_1."time", hyper_1.device, (avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper_2."time", hyper_2.device, (avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (date_trunc('month'::text, "time")), device, avg(temp) - Group Key: (date_trunc('month'::text, "time")), device - -> Sort - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - Sort Key: (date_trunc('month'::text, "time")), device - -> Custom Scan (AsyncAppend) - Output: (date_trunc('month'::text, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (date_trunc('month'::text, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT date_trunc('month'::text, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(27 rows) - - -######### Grouping on time and device (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING device > 4 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND ((device > 4)) GROUP BY 1, 2 -(27 rows) - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, "time")), device, avg(temp) - Group Key: (time_bucket('@ 2 days'::interval, "time")), device - Filter: ((avg(temp) > '40'::double precision) AND (max(temp) < '70'::double precision)) - -> Sort - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - Sort Key: (time_bucket('@ 2 days'::interval, "time")), device - -> Custom Scan (AsyncAppend) - Output: (time_bucket('@ 2 days'::interval, "time")), device, (PARTIAL avg(temp)), (PARTIAL max(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, (PARTIAL avg(hyper1d.temp)), (PARTIAL max(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, (PARTIAL avg(hyper1d_1.temp)), (PARTIAL max(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, (PARTIAL avg(hyper1d_2.temp)), (PARTIAL max(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT public.time_bucket('@ 2 days'::interval, "time"), device, _timescaledb_functions.partialize_agg(avg(temp)), _timescaledb_functions.partialize_agg(max(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(28 rows) - - -######### Grouping on device only (full aggregation) - -EXPLAIN (verbose, costs off) -SELECT device, avg(temp) -FROM hyper -WHERE time >= '2019-01-01' -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper.device - -> Custom Scan (DataNodeScan) - Output: hyper.device, (PARTIAL avg(hyper.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_12_chunk, _dist_hyper_1_13_chunk, _dist_hyper_1_15_chunk, _dist_hyper_1_17_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_1.device, (PARTIAL avg(hyper_1.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_9_chunk, _dist_hyper_1_11_chunk, _dist_hyper_1_14_chunk, _dist_hyper_1_18_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4, 5, 6, 7]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper_2.device, (PARTIAL avg(hyper_2.temp)) - Relations: Aggregate on (public.hyper) - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_10_chunk, _dist_hyper_1_16_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1, 2, 3, 4]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(25 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT location, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' AND (temp * random() >= 0) -GROUP BY 1 -ORDER BY 1 - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize GroupAggregate - Output: location, avg(temp) - Group Key: location - -> Custom Scan (AsyncAppend) - Output: location, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d.location - -> Partial GroupAggregate - Output: hyper1d.location, PARTIAL avg(hyper1d.temp) - Group Key: hyper1d.location - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d.location, hyper1d.temp - Filter: ((hyper1d.temp * random()) >= '0'::double precision) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_1.location, PARTIAL avg(hyper1d_1.temp) - Group Key: hyper1d_1.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.location, hyper1d_1.temp - Filter: ((hyper1d_1.temp * random()) >= '0'::double precision) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST - -> Partial GroupAggregate - Output: hyper1d_2.location, PARTIAL avg(hyper1d_2.temp) - Group Key: hyper1d_2.location - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.location, hyper1d_2.temp - Filter: ((hyper1d_2.temp * random()) >= '0'::double precision) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT location, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY location ASC NULLS LAST -(34 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Finalize GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp), sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Merge Append - Sort Key: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d."time")), hyper1d.device, PARTIAL avg(hyper1d.temp), PARTIAL sum((hyper1d.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_1."time")), hyper1d_1.device, PARTIAL avg(hyper1d_1.temp), PARTIAL sum((hyper1d_1.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper1d_1."time"), hyper1d_1.device, hyper1d_1.temp - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Partial GroupAggregate - Output: (time_bucket('@ 2 days'::interval, hyper1d_2."time")), hyper1d_2.device, PARTIAL avg(hyper1d_2.temp), PARTIAL sum((hyper1d_2.temp * (((random() <= '1'::double precision))::integer)::double precision)) - Group Key: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device - -> Result - Output: time_bucket('@ 2 days'::interval, hyper1d_2."time"), hyper1d_2.device, hyper1d_2.temp - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('2 days'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(35 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) - Group Key: hyper1d."time", hyper1d.device - Filter: ((avg(hyper1d.temp) * (custom_sum(hyper1d.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp) - Group Key: hyper1d_1."time", hyper1d_1.device - Filter: ((avg(hyper1d_1.temp) * (custom_sum(hyper1d_1.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp) - Group Key: hyper1d_2."time", hyper1d_2.device - Filter: ((avg(hyper1d_2.temp) * (custom_sum(hyper1d_2.device))::double precision) > '0.8'::double precision) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(30 rows) - - -######### No push down on some functions - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp), custom_sum(device) -FROM hyper1d -WHERE time >= '2019-01-01' -GROUP BY 1,2 - - - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)), (custom_sum(device)) - -> Append - -> GroupAggregate - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp), custom_sum(hyper1d.device) - Group Key: hyper1d."time", hyper1d.device - -> Custom Scan (DataNodeScan) on public.hyper1d - Output: hyper1d."time", hyper1d.device, hyper1d.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_1."time", hyper1d_1.device, avg(hyper1d_1.temp), custom_sum(hyper1d_1.device) - Group Key: hyper1d_1."time", hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST - -> GroupAggregate - Output: hyper1d_2."time", hyper1d_2.device, avg(hyper1d_2.temp), custom_sum(hyper1d_2.device) - Group Key: hyper1d_2."time", hyper1d_2.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY "time" ASC NULLS LAST, device ASC NULLS LAST -(27 rows) - - -######### Constification and runtime push down of time-related functions - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - tsl_override_current_timestamptz ----------------------------------- - -(1 row) - - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) - Output: "time", device, (avg(temp)) - -> Append - -> Custom Scan (DataNodeScan) - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_1."time", hyper1d_1.device, (avg(hyper1d_1.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 - -> Custom Scan (DataNodeScan) - Output: hyper1d_2."time", hyper1d_2.device, (avg(hyper1d_2.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, avg(temp) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1, 2 -(21 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 5 -OFFSET 5 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 10 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 10 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT 0 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 1 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 1 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT extract(year from date '2000-01-01') - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) LIMIT 2000 - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) LIMIT 2000 -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device -FROM hyper1d - -LIMIT greatest(random(), 10.0) - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d."time", hyper1d.device - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) -(20 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM hyper1d - -LIMIT 10 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit - Output: hyper1d."time", hyper1d.device, (avg(hyper1d.temp) OVER (?)) - -> WindowAgg - Output: hyper1d."time", hyper1d.device, avg(hyper1d.temp) OVER (?) - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time", hyper1d.temp - -> Merge Append - Sort Key: hyper1d_1.device - -> Result - Output: hyper1d_1.device, hyper1d_1."time", hyper1d_1.temp - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper1d_2.device, hyper1d_2."time", hyper1d_2.temp - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Result - Output: hyper1d_3.device, hyper1d_3."time", hyper1d_3.temp - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device, hyper1d_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(29 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device, hyper1d_1."time" - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST, "time" ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - -EXPLAIN (verbose, costs off) -SELECT DISTINCT ON (device) device, time -FROM hyper1d - -LIMIT 10 - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: hyper1d.device, hyper1d."time" - -> Unique - Output: hyper1d.device, hyper1d."time" - -> Custom Scan (AsyncAppend) - Output: hyper1d.device, hyper1d."time" - -> Merge Append - Sort Key: hyper1d_1.device - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1.device, hyper1d_1."time" - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2.device, hyper1d_2."time" - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3.device, hyper1d_3."time" - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT DISTINCT ON (device) "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) ORDER BY device ASC NULLS LAST -(23 rows) - - -######### LIMIT push down cases - - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- - Limit - Output: t."time" - -> Nested Loop - Output: t."time" - Join Filter: (t.device = join_test.device) - -> Custom Scan (AsyncAppend) - Output: t."time", t.device - -> Append - -> Custom Scan (DataNodeScan) on public.hyper1d t_1 - Output: t_1."time", t_1.device - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_2 - Output: t_2."time", t_2.device - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) - -> Custom Scan (DataNodeScan) on public.hyper1d t_3 - Output: t_3."time", t_3.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) - -> Materialize - Output: join_test.device - -> Seq Scan on public.join_test - Output: join_test.device -(27 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -WITH top_n AS ( - SELECT device, avg(temp) - FROM hyper1d - WHERE time >= '2019-01-01' - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM hyper1d INNER JOIN top_n USING (device) -WHERE time >= '2019-01-01' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, hyper1d."time")), hyper1d.device, avg(hyper1d.temp) - Group Key: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, hyper1d."time"), hyper1d.device, hyper1d.temp - Inner Unique: true - Join Filter: (hyper1d.device = top_n.device) - -> Custom Scan (AsyncAppend) - Output: hyper1d."time", hyper1d.device, hyper1d.temp - -> Merge Append - Sort Key: (time_bucket('@ 1 min'::interval, hyper1d_1."time")), hyper1d_1.device - -> Result - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp, time_bucket('@ 1 min'::interval, hyper1d_1."time") - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_1 - Output: hyper1d_1."time", hyper1d_1.device, hyper1d_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp, time_bucket('@ 1 min'::interval, hyper1d_2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_2 - Output: hyper1d_2."time", hyper1d_2.device, hyper1d_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Result - Output: hyper1d_3."time", hyper1d_3.device, hyper1d_3.temp, time_bucket('@ 1 min'::interval, hyper1d_3."time") - -> Custom Scan (DataNodeScan) on public.hyper1d hyper1d_3 - Output: hyper1d_3."time", hyper1d_3.device, hyper1d_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: top_n.device - -> Subquery Scan on top_n - Output: top_n.device - -> Limit - Output: device, (avg(temp)) - -> Sort - Output: device, (avg(temp)) - Sort Key: (avg(temp)) DESC - -> Finalize GroupAggregate - Output: device, avg(temp) - Group Key: device - -> Custom Scan (AsyncAppend) - Output: device, (PARTIAL avg(temp)) - -> Merge Append - Sort Key: hyper1d_4.device - -> Custom Scan (DataNodeScan) - Output: hyper1d_4.device, (PARTIAL avg(hyper1d_4.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_1 - Chunks: _dist_hyper_2_20_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_5.device, (PARTIAL avg(hyper1d_5.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_2 - Chunks: _dist_hyper_2_21_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[8]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST - -> Custom Scan (DataNodeScan) - Output: hyper1d_6.device, (PARTIAL avg(hyper1d_6.temp)) - Relations: Aggregate on (public.hyper1d) - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT device, _timescaledb_functions.partialize_agg(avg(temp)) FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) GROUP BY 1 ORDER BY device ASC NULLS LAST -(66 rows) - - -######### CTEs/Sub-queries - -EXPLAIN (verbose, costs off) -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Output: (time_bucket('@ 1 min'::interval, h1."time")), h1.device, avg(h1.temp), max(h2.temp) - Group Key: time_bucket('@ 1 min'::interval, h1."time"), h1.device - -> Nested Loop - Output: time_bucket('@ 1 min'::interval, h1."time"), h1.device, h1.temp, h2.temp - Join Filter: ((h1.device = h2.device) AND (time_bucket('@ 1 min'::interval, h1."time") = (time_bucket('@ 1 min'::interval, h2."time")))) - -> Result - Output: h2.temp, h2."time", h2.device, time_bucket('@ 1 min'::interval, h2."time") - -> Custom Scan (DataNodeScan) on public.hyper1d h2 - Output: h2.temp, h2."time", h2.device - Data node: db_dist_query_3 - Chunks: _dist_hyper_2_19_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper1d WHERE _timescaledb_functions.chunks_in(public.hyper1d.*, ARRAY[5]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Materialize - Output: h1."time", h1.device, h1.temp - -> Custom Scan (AsyncAppend) - Output: h1."time", h1.device, h1.temp - -> Append - -> Custom Scan (DataNodeScan) on public.hyper h1_1 - Output: h1_1."time", h1_1.device, h1_1.temp - Data node: db_dist_query_1 - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_2 - Output: h1_2."time", h1_2.device, h1_2.temp - Data node: db_dist_query_2 - Chunks: _dist_hyper_1_2_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.hyper h1_3 - Output: h1_3."time", h1_3.device, h1_3.temp - Data node: db_dist_query_3 - Chunks: _dist_hyper_1_3_chunk - Remote SQL: SELECT "time", device, temp FROM public.hyper WHERE _timescaledb_functions.chunks_in(public.hyper.*, ARRAY[1]) AND (("time" >= '2019-01-01 00:00:00-08'::timestamp with time zone)) AND (("time" <= '2019-01-01 15:00:00-08'::timestamp with time zone)) ORDER BY public.time_bucket('00:01:00'::interval, "time") ASC NULLS LAST, device ASC NULLS LAST -(33 rows) - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: reference -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper -%%% PREFIX: -%%% WHERE_CLAUSE: :CLEAN_PARTITIONING_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%% RUNNING TESTS on table: hyper1d -%%% PREFIX: -%%% WHERE_CLAUSE: :REPARTITIONED_TIME_RANGE -%%% ORDER_BY_1: ORDER BY 1 -%%% ORDER_BY_1_2: ORDER BY 1,2 -%%% LIMIT: -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -:DIFF_CMD_UNOPT -:DIFF_CMD_OPT -:DIFF_CMD_REPART -:DIFF_CMD_1DIM -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_ref_table_join-13.out b/tsl/test/expected/dist_ref_table_join-13.out deleted file mode 100644 index f26370a42b6..00000000000 --- a/tsl/test/expected/dist_ref_table_join-13.out +++ /dev/null @@ -1,2151 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set ECHO all -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------+--------------------------+--------------+------------------+------------------- - db_dist_ref_table_join_1 | db_dist_ref_table_join_1 | t | t | t - db_dist_ref_table_join_2 | db_dist_ref_table_join_2 | t | t | t - db_dist_ref_table_join_3 | db_dist_ref_table_join_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -\des - List of foreign servers - Name | Owner | Foreign-data wrapper ---------------------------+--------------------+---------------------- - db_dist_ref_table_join_1 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_2 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_3 | cluster_super_user | timescaledb_fdw -(3 rows) - -drop table if exists metric; -NOTICE: table "metric" does not exist, skipping -CREATE table metric(ts timestamptz, id int, value float); -SELECT create_distributed_hypertable('metric', 'ts', 'id'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "ts" - create_distributed_hypertable -------------------------------- - (1,public,metric,t) -(1 row) - -INSERT into metric values ('2022-02-02 02:02:02+03', 1, 50); -INSERT into metric values ('2020-01-01 01:01:01+03', 1, 60); -INSERT into metric values ('2000-03-03 03:03:03+03', 1, 70); -INSERT into metric values ('2000-04-04 04:04:03+03', 2, 80); --- Reference table with generic replication -CREATE table metric_name(id int primary key, name text); -INSERT into metric_name values (1, 'cpu1'); -INSERT into metric_name values (2, 'cpu2'); -CALL distributed_exec($$CREATE table metric_name(id int primary key, name text);$$); -CALL distributed_exec($$INSERT into metric_name values (1, 'cpu1');$$); -CALL distributed_exec($$INSERT into metric_name values (2, 'cpu2');$$); --- The reference table as DHT -CREATE TABLE metric_name_dht(id BIGSERIAL, name text); -SELECT create_distributed_hypertable('metric_name_dht', 'id', chunk_time_interval => 9223372036854775807, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,metric_name_dht,t) -(1 row) - -INSERT into metric_name_dht (id, name) values (1, 'cpu1'); -INSERT into metric_name_dht (id, name) values (2, 'cpu2'); --- A local version of the reference table -CREATE table metric_name_local(id int primary key, name text); -INSERT into metric_name_local values (1, 'cpu1'); -INSERT into metric_name_local values (2, 'cpu2'); -CREATE table reference_table2(id int primary key, name text); -SELECT create_distributed_hypertable('reference_table2', 'id', chunk_time_interval => 2147483647, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (3,public,reference_table2,t) -(1 row) - -CREATE table local_table(id int primary key, name text); -SET client_min_messages TO WARNING; --- Create a table in a different schema -CREATE SCHEMA test1; -GRANT CREATE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -GRANT USAGE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -CREATE table test1.table_in_schema(id int primary key, name text); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, reference_table2'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_dht'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - -\set ON_ERROR_STOP 0 --- Try to declare a non existing table as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, non_existing_table'); -ERROR: table "non_existing_table" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - --- Try to declare a hypertable as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, metric'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to add an empty field -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, , metric'); -ERROR: parameter "reference_tables" must be a comma-separated list of reference table names -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to declare a view as reference table -CREATE VIEW metric_name_view AS SELECT * FROM metric_name; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_view'); -ERROR: relation "metric_name_view" is not an ordinary table. Only ordinary tables can be used as reference tables -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to use a table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - --- Try to use a non-existing table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema_non_existing'); -ERROR: table "test1.table_in_schema_non_existing" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - -\set ON_ERROR_STOP 1 --- Set empty options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables ''); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------- - {reference_tables=} -(1 row) - --- Remove options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP reference_tables); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - --- Set options again -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, metric_name_dht, reference_table2'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht, reference_table2"} -(1 row) - -SET client_min_messages TO DEBUG1; -\set PREFIX 'EXPLAIN (analyze, verbose, costs off, timing off, summary off)' --- Analyze tables -ANALYZE metric; -LOG: statement: ANALYZE metric; -ANALYZE metric_name; -LOG: statement: ANALYZE metric_name; -ANALYZE metric_name_dht; -LOG: statement: ANALYZE metric_name_dht; --- Our cost model for these kinds of plans is not so good yet, so make some --- tweaks to always get the join pushdown. -set timescaledb.enable_parameterized_data_node_scan to false; -LOG: statement: set timescaledb.enable_parameterized_data_node_scan to false; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -------- --- Tests based on results -------- --- Simple join -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - --- Filter -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 -(1 row) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(3 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+----+-------+------ -(0 rows) - --- Ordering -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(4 rows) - --- Aggregations -SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Aggregations and Renaming -SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Grouping -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu1 | 70 | 50 - cpu2 | 80 | 80 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 - cpu1 | 70 | 50 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 -(1 row) - -------- --- Tests based on query plans -------- --- Tests without filter (vanilla PostgreSQL reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests without filter (DHT reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with filter pushdown -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -LOG: statement: PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -:PREFIX -EXECUTE prepared_join_pushdown_value(10); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -EXECUTE prepared_join_pushdown_value(10); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts > '2022-02-01 15:02:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with an expression that evaluates to false -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with aliases -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with projections -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.value FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: m1.id, m1.id - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r2.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.id, r5.value, r2.id, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - --- Ordering -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name, metric_1.value DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST, r8.value DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST, r9.value DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - --- Ordering with explicit table qualification -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id, metric.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id, metric_1.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r8.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r9.id ASC NULLS LAST -(16 rows) - --- Ordering with explicit table qualification and aliases -:PREFIX -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.name, m1.value, m1.id, m2.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: m1_1.value, m2.name, m1_1.id, m2.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.value, m1_1.id, m2.name, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r8.id ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.value, m1_2.id, m2.name, m2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r9.id ASC NULLS LAST, r2.id ASC NULLS LAST -(16 rows) - --- Grouping -:PREFIX -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Group (actual rows=2 loops=1) - Output: metric_name.name - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - -:PREFIX -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=1 loops=1) - Output: metric_name.name, max(metric.value) - Group Key: metric_name.name - -> Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(11 rows) - --- Grouping and sorting -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(19 rows) - --- Having -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - Filter: (min(metric.value) > '0'::double precision) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(20 rows) - --- Rank -:PREFIX -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg (actual rows=4 loops=1) - Output: metric_name_local.name, metric.value, rank() OVER (?) - -> Nested Loop (actual rows=4 loops=1) - Output: metric.value, metric_name_local.name - Inner Unique: true - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) ORDER BY value ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) ORDER BY value ASC NULLS LAST - -> Index Scan using metric_name_local_pkey on public.metric_name_local (actual rows=1 loops=4) - Output: metric_name_local.id, metric_name_local.name - Index Cond: (metric_name_local.id = metric.id) -(24 rows) - --- Check returned types -SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -LOG: statement: SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -DEBUG: try to push down a join on a reference table - pg_typeof | pg_typeof | pg_typeof | name | id | value ------------+-----------+------------------+------+----+------- - text | integer | double precision | cpu1 | 1 | 50 -(1 row) - --- Left join and reference table on the left hypertable on the right (no pushdown) -:PREFIX -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - Join Filter: (metric_name.id = metric.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Right join reference table on the left, hypertable on the right (can be converted into a left join by PostgreSQL, pushdown) -:PREFIX -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric_name.name, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name, metric_1.id, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.name, r8.id, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name, metric_2.id, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.name, r9.id, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Right join hypertable on the left, reference table on the right (no pushdown) -:PREFIX -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric.ts, metric.value, metric_name.name - Join Filter: (metric.id = metric_name.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Inner join and reference table left, hypertable on the right (pushdown) -:PREFIX -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.id, metric_name.name, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.id, r1.name, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.id, metric_name.name, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.id, r1.name, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, hypertable left, reference table right (pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, reference table left, hypertable right (pushdown) -:PREFIX -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.id, m2.value, m1.id, m1.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.id, m2_1.value, m1.id, m1.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.id, m2_2.value, m1.id, m1.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on three tables (no pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name, m3.id, m3.name - Inner Unique: true - Join Filter: (m1.id = m3.id) - Rows Removed by Join Filter: 1 - -> Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=1 loops=4) - Output: m2.id, m2.name - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.id, m2.name - -> Materialize (actual rows=1 loops=4) - Output: m3.id, m3.name - -> Seq Scan on public.metric_name m3 (actual rows=2 loops=1) - Output: m3.id, m3.name - Filter: (m3.name ~~ 'cpu%'::text) -(34 rows) - --- Left join on a DHT and a subselect on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a DHT and a subselect with filter on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a subselect on a DHT and a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r2.id, r2.name FROM (public.metric r10 INNER JOIN public.metric_name r2 ON (((r10.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join and hypertable on left and right (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - -> Custom Scan (DataNodeScan) on public.metric m1 (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=0 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) AND ((id = 2)) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) -(24 rows) - --- Left join and reference table on left and right -:PREFIX -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; - QUERY PLAN ------------------------------------------------------------------------ - Nested Loop Left Join (actual rows=2 loops=1) - Output: m1.id, m1.name, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Seq Scan on public.metric_name m1 (actual rows=2 loops=1) - Output: m1.id, m1.name - Filter: (m1.name ~~ 'cpu%'::text) - -> Materialize (actual rows=2 loops=2) - Output: m2.name, m2.id - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.name, m2.id -(12 rows) - --- Only aggregation no values needs to be transferred -:PREFIX -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=1) - Output: count(*) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT NULL FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT NULL FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(14 rows) - --- Lateral joins that can be converted into regular joins -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Lateral join that can not be converted and pushed down -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Limit (actual rows=0 loops=4) - Output: m2.id, m2.name - -> Sort (actual rows=0 loops=4) - Output: m2.id, m2.name - Sort Key: m2.name - Sort Method: quicksort - -> Seq Scan on public.metric_name m2 (actual rows=0 loops=4) - Output: m2.id, m2.name - Filter: (m1.id > m2.id) - Rows Removed by Filter: 2 -(27 rows) - --- Two left joins (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value, mn.name - Inner Unique: true - Hash Cond: (m1.id = mn.id) - -> Nested Loop Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 6 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=4 loops=4) - Output: m2.ts, m2.value, m2.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Hash (actual rows=2 loops=1) - Output: mn.name, mn.id - Buckets: 1024 Batches: 1 - -> Seq Scan on public.metric_name mn (actual rows=2 loops=1) - Output: mn.name, mn.id -(45 rows) - -------- --- Tests with shippable and non-shippable joins / EquivalenceClass --- See 'dist_param.sql' for an explanation of the used textin / int4out --- functions. -------- --- Shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r8.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r9.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - --- Non-shippable equality class join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Merge Join (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Merge Cond: ((concat('cpu', metric.id)) = metric_name.name) - -> Sort (actual rows=4 loops=1) - Output: metric.value, metric.id, (concat('cpu', metric.id)) - Sort Key: (concat('cpu', metric.id)) - Sort Method: quicksort - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id, concat('cpu', metric.id) - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Sort (actual rows=4 loops=1) - Output: metric_name.name - Sort Key: metric_name.name - Sort Method: quicksort - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(31 rows) - --- Non-shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Sort (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Sort Key: metric_name.name - Sort Method: quicksort - -> Nested Loop (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Join Filter: texteq(concat('cpu', textin(int4out(metric.id))), metric_name.name) - Rows Removed by Join Filter: 4 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=2 loops=4) - Output: metric_name.name - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(30 rows) - -------- --- MERGE is supported in PG >= 15. Currently, it is not supported in TimescaleDB --- on distributed hypertables. Perform a MERGE here to check if the join pushdown --- can handle the MERGE command properly. ON_ERROR_STOP is disabled for this test. --- Older PostgreSQL versions report an error because MERGE is not supported. This --- will be ignored due to the setting. --- Commenting below test as error meesage is different on windows vs unix. --- Issue #5725 is opened to track it. -------- --- \set ON_ERROR_STOP 0 --- MERGE INTO metric as target_0 --- USING metric as input_0 --- inner join (select id from metric_name as input_1) as subq_0 --- ON (TRUE) --- ON target_0.id = input_0.id --- WHEN MATCHED --- THEN DO NOTHING --- WHEN NOT MATCHED --- THEN DO NOTHING; --- \set ON_ERROR_STOP 1 -------- --- Tests without enable_per_data_node_queries (no pushdown supported) -------- -SET timescaledb.enable_per_data_node_queries = false; -LOG: statement: SET timescaledb.enable_per_data_node_queries = false; -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: join on reference table is not considered to be pushed down because 'enable_per_data_node_queries' GUC is disabled - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value, metric_name.name - Inner Unique: true - Join Filter: (_dist_hyper_1_1_chunk.id = metric_name.id) - Rows Removed by Join Filter: 1 - -> Append (actual rows=4 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_1_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.id, _dist_hyper_1_2_chunk.ts, _dist_hyper_1_2_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_2_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.id, _dist_hyper_1_3_chunk.ts, _dist_hyper_1_3_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_3_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_4_chunk.id, _dist_hyper_1_4_chunk.ts, _dist_hyper_1_4_chunk.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_4_chunk - -> Materialize (actual rows=1 loops=4) - Output: metric_name.name, metric_name.id - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name, metric_name.id -(30 rows) - -SET timescaledb.enable_per_data_node_queries = true; -LOG: statement: SET timescaledb.enable_per_data_node_queries = true; -------- --- Tests with empty reftable -------- -RESET client_min_messages; -LOG: statement: RESET client_min_messages; -TRUNCATE metric_name; -CALL distributed_exec($$TRUNCATE metric_name;$$); --- Left join -SELECT * FROM metric LEFT JOIN metric_name USING (id); - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | -(4 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Inner join -SELECT * FROM metric JOIN metric_name USING (id); - id | ts | value | name -----+----+-------+------ -(0 rows) - -:PREFIX -SELECT * FROM metric JOIN metric_name USING (id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Filter on the NULL column -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name IS NOT NULL; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -------- --- Drop reftable on DNs and check proper error reporting -------- -\set ON_ERROR_STOP 0 -CALL distributed_exec($$DROP table metric_name;$$); -SELECT * FROM metric LEFT JOIN metric_name USING (id); -ERROR: [db_dist_ref_table_join_1]: relation "public.metric_name" does not exist diff --git a/tsl/test/expected/dist_ref_table_join-14.out b/tsl/test/expected/dist_ref_table_join-14.out deleted file mode 100644 index f26370a42b6..00000000000 --- a/tsl/test/expected/dist_ref_table_join-14.out +++ /dev/null @@ -1,2151 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set ECHO all -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------+--------------------------+--------------+------------------+------------------- - db_dist_ref_table_join_1 | db_dist_ref_table_join_1 | t | t | t - db_dist_ref_table_join_2 | db_dist_ref_table_join_2 | t | t | t - db_dist_ref_table_join_3 | db_dist_ref_table_join_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -\des - List of foreign servers - Name | Owner | Foreign-data wrapper ---------------------------+--------------------+---------------------- - db_dist_ref_table_join_1 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_2 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_3 | cluster_super_user | timescaledb_fdw -(3 rows) - -drop table if exists metric; -NOTICE: table "metric" does not exist, skipping -CREATE table metric(ts timestamptz, id int, value float); -SELECT create_distributed_hypertable('metric', 'ts', 'id'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "ts" - create_distributed_hypertable -------------------------------- - (1,public,metric,t) -(1 row) - -INSERT into metric values ('2022-02-02 02:02:02+03', 1, 50); -INSERT into metric values ('2020-01-01 01:01:01+03', 1, 60); -INSERT into metric values ('2000-03-03 03:03:03+03', 1, 70); -INSERT into metric values ('2000-04-04 04:04:03+03', 2, 80); --- Reference table with generic replication -CREATE table metric_name(id int primary key, name text); -INSERT into metric_name values (1, 'cpu1'); -INSERT into metric_name values (2, 'cpu2'); -CALL distributed_exec($$CREATE table metric_name(id int primary key, name text);$$); -CALL distributed_exec($$INSERT into metric_name values (1, 'cpu1');$$); -CALL distributed_exec($$INSERT into metric_name values (2, 'cpu2');$$); --- The reference table as DHT -CREATE TABLE metric_name_dht(id BIGSERIAL, name text); -SELECT create_distributed_hypertable('metric_name_dht', 'id', chunk_time_interval => 9223372036854775807, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,metric_name_dht,t) -(1 row) - -INSERT into metric_name_dht (id, name) values (1, 'cpu1'); -INSERT into metric_name_dht (id, name) values (2, 'cpu2'); --- A local version of the reference table -CREATE table metric_name_local(id int primary key, name text); -INSERT into metric_name_local values (1, 'cpu1'); -INSERT into metric_name_local values (2, 'cpu2'); -CREATE table reference_table2(id int primary key, name text); -SELECT create_distributed_hypertable('reference_table2', 'id', chunk_time_interval => 2147483647, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (3,public,reference_table2,t) -(1 row) - -CREATE table local_table(id int primary key, name text); -SET client_min_messages TO WARNING; --- Create a table in a different schema -CREATE SCHEMA test1; -GRANT CREATE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -GRANT USAGE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -CREATE table test1.table_in_schema(id int primary key, name text); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, reference_table2'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_dht'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - -\set ON_ERROR_STOP 0 --- Try to declare a non existing table as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, non_existing_table'); -ERROR: table "non_existing_table" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - --- Try to declare a hypertable as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, metric'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to add an empty field -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, , metric'); -ERROR: parameter "reference_tables" must be a comma-separated list of reference table names -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to declare a view as reference table -CREATE VIEW metric_name_view AS SELECT * FROM metric_name; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_view'); -ERROR: relation "metric_name_view" is not an ordinary table. Only ordinary tables can be used as reference tables -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to use a table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - --- Try to use a non-existing table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema_non_existing'); -ERROR: table "test1.table_in_schema_non_existing" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - -\set ON_ERROR_STOP 1 --- Set empty options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables ''); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------- - {reference_tables=} -(1 row) - --- Remove options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP reference_tables); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - --- Set options again -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, metric_name_dht, reference_table2'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht, reference_table2"} -(1 row) - -SET client_min_messages TO DEBUG1; -\set PREFIX 'EXPLAIN (analyze, verbose, costs off, timing off, summary off)' --- Analyze tables -ANALYZE metric; -LOG: statement: ANALYZE metric; -ANALYZE metric_name; -LOG: statement: ANALYZE metric_name; -ANALYZE metric_name_dht; -LOG: statement: ANALYZE metric_name_dht; --- Our cost model for these kinds of plans is not so good yet, so make some --- tweaks to always get the join pushdown. -set timescaledb.enable_parameterized_data_node_scan to false; -LOG: statement: set timescaledb.enable_parameterized_data_node_scan to false; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -------- --- Tests based on results -------- --- Simple join -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - --- Filter -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 -(1 row) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(3 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+----+-------+------ -(0 rows) - --- Ordering -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(4 rows) - --- Aggregations -SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Aggregations and Renaming -SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Grouping -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu1 | 70 | 50 - cpu2 | 80 | 80 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 - cpu1 | 70 | 50 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 -(1 row) - -------- --- Tests based on query plans -------- --- Tests without filter (vanilla PostgreSQL reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests without filter (DHT reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with filter pushdown -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -LOG: statement: PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -:PREFIX -EXECUTE prepared_join_pushdown_value(10); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -EXECUTE prepared_join_pushdown_value(10); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts > '2022-02-01 15:02:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with an expression that evaluates to false -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with aliases -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with projections -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.value FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: m1.id, m1.id - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r2.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.id, r5.value, r2.id, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - --- Ordering -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name, metric_1.value DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST, r8.value DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST, r9.value DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(16 rows) - --- Ordering with explicit table qualification -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST -(16 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id, metric.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id, metric_1.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r8.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r9.id ASC NULLS LAST -(16 rows) - --- Ordering with explicit table qualification and aliases -:PREFIX -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.name, m1.value, m1.id, m2.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: m1_1.value, m2.name, m1_1.id, m2.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.value, m1_1.id, m2.name, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r8.id ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.value, m1_2.id, m2.name, m2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r9.id ASC NULLS LAST, r2.id ASC NULLS LAST -(16 rows) - --- Grouping -:PREFIX -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Group (actual rows=2 loops=1) - Output: metric_name.name - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - -:PREFIX -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=1 loops=1) - Output: metric_name.name, max(metric.value) - Group Key: metric_name.name - -> Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(11 rows) - --- Grouping and sorting -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(19 rows) - --- Having -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - Filter: (min(metric.value) > '0'::double precision) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(20 rows) - --- Rank -:PREFIX -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg (actual rows=4 loops=1) - Output: metric_name_local.name, metric.value, rank() OVER (?) - -> Nested Loop (actual rows=4 loops=1) - Output: metric.value, metric_name_local.name - Inner Unique: true - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) ORDER BY value ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) ORDER BY value ASC NULLS LAST - -> Index Scan using metric_name_local_pkey on public.metric_name_local (actual rows=1 loops=4) - Output: metric_name_local.id, metric_name_local.name - Index Cond: (metric_name_local.id = metric.id) -(24 rows) - --- Check returned types -SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -LOG: statement: SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -DEBUG: try to push down a join on a reference table - pg_typeof | pg_typeof | pg_typeof | name | id | value ------------+-----------+------------------+------+----+------- - text | integer | double precision | cpu1 | 1 | 50 -(1 row) - --- Left join and reference table on the left hypertable on the right (no pushdown) -:PREFIX -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - Join Filter: (metric_name.id = metric.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Right join reference table on the left, hypertable on the right (can be converted into a left join by PostgreSQL, pushdown) -:PREFIX -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric_name.name, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name, metric_1.id, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.name, r8.id, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name, metric_2.id, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.name, r9.id, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Right join hypertable on the left, reference table on the right (no pushdown) -:PREFIX -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric.ts, metric.value, metric_name.name - Join Filter: (metric.id = metric_name.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Inner join and reference table left, hypertable on the right (pushdown) -:PREFIX -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.id, metric_name.name, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.id, r1.name, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.id, metric_name.name, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.id, r1.name, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, hypertable left, reference table right (pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, reference table left, hypertable right (pushdown) -:PREFIX -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.id, m2.value, m1.id, m1.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.id, m2_1.value, m1.id, m1.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.id, m2_2.value, m1.id, m1.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on three tables (no pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name, m3.id, m3.name - Inner Unique: true - Join Filter: (m1.id = m3.id) - Rows Removed by Join Filter: 1 - -> Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=1 loops=4) - Output: m2.id, m2.name - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.id, m2.name - -> Materialize (actual rows=1 loops=4) - Output: m3.id, m3.name - -> Seq Scan on public.metric_name m3 (actual rows=2 loops=1) - Output: m3.id, m3.name - Filter: (m3.name ~~ 'cpu%'::text) -(34 rows) - --- Left join on a DHT and a subselect on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a DHT and a subselect with filter on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a subselect on a DHT and a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r2.id, r2.name FROM (public.metric r10 INNER JOIN public.metric_name r2 ON (((r10.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join and hypertable on left and right (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - -> Custom Scan (DataNodeScan) on public.metric m1 (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=0 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) AND ((id = 2)) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) -(24 rows) - --- Left join and reference table on left and right -:PREFIX -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; - QUERY PLAN ------------------------------------------------------------------------ - Nested Loop Left Join (actual rows=2 loops=1) - Output: m1.id, m1.name, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Seq Scan on public.metric_name m1 (actual rows=2 loops=1) - Output: m1.id, m1.name - Filter: (m1.name ~~ 'cpu%'::text) - -> Materialize (actual rows=2 loops=2) - Output: m2.name, m2.id - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.name, m2.id -(12 rows) - --- Only aggregation no values needs to be transferred -:PREFIX -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=1) - Output: count(*) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT NULL FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT NULL FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(14 rows) - --- Lateral joins that can be converted into regular joins -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Lateral join that can not be converted and pushed down -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Limit (actual rows=0 loops=4) - Output: m2.id, m2.name - -> Sort (actual rows=0 loops=4) - Output: m2.id, m2.name - Sort Key: m2.name - Sort Method: quicksort - -> Seq Scan on public.metric_name m2 (actual rows=0 loops=4) - Output: m2.id, m2.name - Filter: (m1.id > m2.id) - Rows Removed by Filter: 2 -(27 rows) - --- Two left joins (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value, mn.name - Inner Unique: true - Hash Cond: (m1.id = mn.id) - -> Nested Loop Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 6 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=4 loops=4) - Output: m2.ts, m2.value, m2.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Hash (actual rows=2 loops=1) - Output: mn.name, mn.id - Buckets: 1024 Batches: 1 - -> Seq Scan on public.metric_name mn (actual rows=2 loops=1) - Output: mn.name, mn.id -(45 rows) - -------- --- Tests with shippable and non-shippable joins / EquivalenceClass --- See 'dist_param.sql' for an explanation of the used textin / int4out --- functions. -------- --- Shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r8.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r9.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - --- Non-shippable equality class join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Merge Join (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Merge Cond: ((concat('cpu', metric.id)) = metric_name.name) - -> Sort (actual rows=4 loops=1) - Output: metric.value, metric.id, (concat('cpu', metric.id)) - Sort Key: (concat('cpu', metric.id)) - Sort Method: quicksort - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id, concat('cpu', metric.id) - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Sort (actual rows=4 loops=1) - Output: metric_name.name - Sort Key: metric_name.name - Sort Method: quicksort - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(31 rows) - --- Non-shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Sort (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Sort Key: metric_name.name - Sort Method: quicksort - -> Nested Loop (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Join Filter: texteq(concat('cpu', textin(int4out(metric.id))), metric_name.name) - Rows Removed by Join Filter: 4 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=2 loops=4) - Output: metric_name.name - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(30 rows) - -------- --- MERGE is supported in PG >= 15. Currently, it is not supported in TimescaleDB --- on distributed hypertables. Perform a MERGE here to check if the join pushdown --- can handle the MERGE command properly. ON_ERROR_STOP is disabled for this test. --- Older PostgreSQL versions report an error because MERGE is not supported. This --- will be ignored due to the setting. --- Commenting below test as error meesage is different on windows vs unix. --- Issue #5725 is opened to track it. -------- --- \set ON_ERROR_STOP 0 --- MERGE INTO metric as target_0 --- USING metric as input_0 --- inner join (select id from metric_name as input_1) as subq_0 --- ON (TRUE) --- ON target_0.id = input_0.id --- WHEN MATCHED --- THEN DO NOTHING --- WHEN NOT MATCHED --- THEN DO NOTHING; --- \set ON_ERROR_STOP 1 -------- --- Tests without enable_per_data_node_queries (no pushdown supported) -------- -SET timescaledb.enable_per_data_node_queries = false; -LOG: statement: SET timescaledb.enable_per_data_node_queries = false; -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: join on reference table is not considered to be pushed down because 'enable_per_data_node_queries' GUC is disabled - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value, metric_name.name - Inner Unique: true - Join Filter: (_dist_hyper_1_1_chunk.id = metric_name.id) - Rows Removed by Join Filter: 1 - -> Append (actual rows=4 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_1_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.id, _dist_hyper_1_2_chunk.ts, _dist_hyper_1_2_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_2_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.id, _dist_hyper_1_3_chunk.ts, _dist_hyper_1_3_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_3_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_4_chunk.id, _dist_hyper_1_4_chunk.ts, _dist_hyper_1_4_chunk.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_4_chunk - -> Materialize (actual rows=1 loops=4) - Output: metric_name.name, metric_name.id - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name, metric_name.id -(30 rows) - -SET timescaledb.enable_per_data_node_queries = true; -LOG: statement: SET timescaledb.enable_per_data_node_queries = true; -------- --- Tests with empty reftable -------- -RESET client_min_messages; -LOG: statement: RESET client_min_messages; -TRUNCATE metric_name; -CALL distributed_exec($$TRUNCATE metric_name;$$); --- Left join -SELECT * FROM metric LEFT JOIN metric_name USING (id); - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | -(4 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Inner join -SELECT * FROM metric JOIN metric_name USING (id); - id | ts | value | name -----+----+-------+------ -(0 rows) - -:PREFIX -SELECT * FROM metric JOIN metric_name USING (id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Filter on the NULL column -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name IS NOT NULL; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -------- --- Drop reftable on DNs and check proper error reporting -------- -\set ON_ERROR_STOP 0 -CALL distributed_exec($$DROP table metric_name;$$); -SELECT * FROM metric LEFT JOIN metric_name USING (id); -ERROR: [db_dist_ref_table_join_1]: relation "public.metric_name" does not exist diff --git a/tsl/test/expected/dist_ref_table_join-15.out b/tsl/test/expected/dist_ref_table_join-15.out deleted file mode 100644 index 0ae8d29edaa..00000000000 --- a/tsl/test/expected/dist_ref_table_join-15.out +++ /dev/null @@ -1,2195 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set ECHO all -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------------+--------------------------+--------------+------------------+------------------- - db_dist_ref_table_join_1 | db_dist_ref_table_join_1 | t | t | t - db_dist_ref_table_join_2 | db_dist_ref_table_join_2 | t | t | t - db_dist_ref_table_join_3 | db_dist_ref_table_join_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -\des - List of foreign servers - Name | Owner | Foreign-data wrapper ---------------------------+--------------------+---------------------- - db_dist_ref_table_join_1 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_2 | cluster_super_user | timescaledb_fdw - db_dist_ref_table_join_3 | cluster_super_user | timescaledb_fdw -(3 rows) - -drop table if exists metric; -NOTICE: table "metric" does not exist, skipping -CREATE table metric(ts timestamptz, id int, value float); -SELECT create_distributed_hypertable('metric', 'ts', 'id'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "ts" - create_distributed_hypertable -------------------------------- - (1,public,metric,t) -(1 row) - -INSERT into metric values ('2022-02-02 02:02:02+03', 1, 50); -INSERT into metric values ('2020-01-01 01:01:01+03', 1, 60); -INSERT into metric values ('2000-03-03 03:03:03+03', 1, 70); -INSERT into metric values ('2000-04-04 04:04:03+03', 2, 80); --- Reference table with generic replication -CREATE table metric_name(id int primary key, name text); -INSERT into metric_name values (1, 'cpu1'); -INSERT into metric_name values (2, 'cpu2'); -CALL distributed_exec($$CREATE table metric_name(id int primary key, name text);$$); -CALL distributed_exec($$INSERT into metric_name values (1, 'cpu1');$$); -CALL distributed_exec($$INSERT into metric_name values (2, 'cpu2');$$); --- The reference table as DHT -CREATE TABLE metric_name_dht(id BIGSERIAL, name text); -SELECT create_distributed_hypertable('metric_name_dht', 'id', chunk_time_interval => 9223372036854775807, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (2,public,metric_name_dht,t) -(1 row) - -INSERT into metric_name_dht (id, name) values (1, 'cpu1'); -INSERT into metric_name_dht (id, name) values (2, 'cpu2'); --- A local version of the reference table -CREATE table metric_name_local(id int primary key, name text); -INSERT into metric_name_local values (1, 'cpu1'); -INSERT into metric_name_local values (2, 'cpu2'); -CREATE table reference_table2(id int primary key, name text); -SELECT create_distributed_hypertable('reference_table2', 'id', chunk_time_interval => 2147483647, replication_factor => 3); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (3,public,reference_table2,t) -(1 row) - -CREATE table local_table(id int primary key, name text); -SET client_min_messages TO WARNING; --- Create a table in a different schema -CREATE SCHEMA test1; -GRANT CREATE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -GRANT USAGE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -CREATE table test1.table_in_schema(id int primary key, name text); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, reference_table2'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_dht'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - -\set ON_ERROR_STOP 0 --- Try to declare a non existing table as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, non_existing_table'); -ERROR: table "non_existing_table" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht"} -(1 row) - --- Try to declare a hypertable as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, metric'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to add an empty field -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, , metric'); -ERROR: parameter "reference_tables" must be a comma-separated list of reference table names -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to declare a view as reference table -CREATE VIEW metric_name_view AS SELECT * FROM metric_name; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_view'); -ERROR: relation "metric_name_view" is not an ordinary table. Only ordinary tables can be used as reference tables -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------------------------- - {"reference_tables=metric_name, reference_table2, metric"} -(1 row) - --- Try to use a table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - --- Try to use a non-existing table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema_non_existing'); -ERROR: table "test1.table_in_schema_non_existing" does not exist -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------------------------------------- - {reference_tables=test1.table_in_schema} -(1 row) - -\set ON_ERROR_STOP 1 --- Set empty options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables ''); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------- - {reference_tables=} -(1 row) - --- Remove options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP reference_tables); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ------------- - -(1 row) - --- Set options again -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, metric_name_dht, reference_table2'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - fdwoptions ---------------------------------------------------------------------- - {"reference_tables=metric_name, metric_name_dht, reference_table2"} -(1 row) - -SET client_min_messages TO DEBUG1; -\set PREFIX 'EXPLAIN (analyze, verbose, costs off, timing off, summary off)' --- Analyze tables -ANALYZE metric; -LOG: statement: ANALYZE metric; -ANALYZE metric_name; -LOG: statement: ANALYZE metric_name; -ANALYZE metric_name_dht; -LOG: statement: ANALYZE metric_name_dht; --- Our cost model for these kinds of plans is not so good yet, so make some --- tweaks to always get the join pushdown. -set timescaledb.enable_parameterized_data_node_scan to false; -LOG: statement: set timescaledb.enable_parameterized_data_node_scan to false; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -LOG: statement: ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); -------- --- Tests based on results -------- --- Simple join -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - --- Filter -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 -(1 row) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(3 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+----+-------+------ -(0 rows) - --- Ordering -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 -(4 rows) - -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -LOG: statement: SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; -DEBUG: try to push down a join on a reference table - id | ts | value | name -----+------------------------------+-------+------ - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | cpu2 - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | cpu1 - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | cpu1 - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | cpu1 -(4 rows) - --- Aggregations -SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Aggregations and Renaming -SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - sum ------ - 180 -(1 row) - -SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - max | min ------+----- - 70 | 50 -(1 row) - -SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -LOG: statement: SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; -DEBUG: try to push down a join on a reference table - count -------- - 3 -(1 row) - --- Grouping -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu1 | 70 | 50 - cpu2 | 80 | 80 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 - cpu1 | 70 | 50 -(2 rows) - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -LOG: statement: SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - name | max | min -------+-----+----- - cpu2 | 80 | 80 -(1 row) - -------- --- Tests based on query plans -------- --- Tests without filter (vanilla PostgreSQL reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests without filter (DHT reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(17 rows) - --- Tests with filter pushdown -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -LOG: statement: PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; -:PREFIX -EXECUTE prepared_join_pushdown_value(10); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -EXECUTE prepared_join_pushdown_value(10); -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts > '2022-02-01 15:02:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 LEFT JOIN public.metric_name r2 ON (((r5.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name_dht.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name_dht.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name_dht r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name_dht.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name_dht r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(17 rows) - --- Tests with an expression that evaluates to false -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu1'::text)) AND ((r2.name ~~ 'cpu2'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with aliases -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) AND ((r8.value > 10::double precision)) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) AND ((r9.value > 10::double precision)) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.value > 10::double precision)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Tests with projections -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.value FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=1 loops=1) - Output: m1.id, m1.id - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(8 rows) - -:PREFIX -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r2.id FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.ts, r5.id, r5.value, r2.id, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.id, r5.ts, r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) -(6 rows) - --- Ordering -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS LAST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name, metric_1.value DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST, r8.value DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST, r9.value DESC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name DESC NULLS FIRST -(18 rows) - --- Ordering with explicit table qualification -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name, metric_name.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST -(18 rows) - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value, metric_name.id, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id, metric_name.name, metric_name.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value, metric_name.name, metric_name.id, metric_1.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r8.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id, metric_name.name, metric_name.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r2.id ASC NULLS LAST, r9.id ASC NULLS LAST -(18 rows) - --- Ordering with explicit table qualification and aliases -:PREFIX -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Result (actual rows=4 loops=1) - Output: m2.name, m1.value, m1.id, m2.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.value, m1.id, m2.name, m2.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: m1_1.value, m2.name, m1_1.id, m2.id - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.value, m1_1.id, m2.name, m2.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r8.id, r2.name, r2.id FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r8.value ASC NULLS LAST, r2.name ASC NULLS LAST, r8.id ASC NULLS LAST, r2.id ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.value, m1_2.id, m2.name, m2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r9.id, r2.name, r2.id FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r9.value ASC NULLS LAST, r2.name ASC NULLS LAST, r9.id ASC NULLS LAST, r2.id ASC NULLS LAST -(18 rows) - --- Grouping -:PREFIX -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Group (actual rows=2 loops=1) - Output: metric_name.name - Group Key: metric_name.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(19 rows) - -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(21 rows) - -:PREFIX -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=1 loops=1) - Output: metric_name.name, max(metric.value) - Group Key: metric_name.name - -> Result (actual rows=1 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk - Remote SQL: SELECT r5.value, r2.name FROM (public.metric r5 INNER JOIN public.metric_name r2 ON (((r5.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r5.ts >= '2022-02-01 15:02:02-08'::timestamp with time zone)) AND ((r5.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r5, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(11 rows) - --- Grouping and sorting -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - -> Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(21 rows) - --- Having -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), min(metric.value) - Group Key: metric_name.name - Filter: (min(metric.value) > '0'::double precision) - -> Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name DESC - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r8.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r8.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name DESC NULLS FIRST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)) AND ((r9.ts >= '2000-02-01 15:02:02-08'::timestamp with time zone)) AND ((r9.ts <= '2022-02-01 15:12:02-08'::timestamp with time zone)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name DESC NULLS FIRST -(22 rows) - --- Rank -:PREFIX -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - WindowAgg (actual rows=4 loops=1) - Output: metric_name_local.name, metric.value, rank() OVER (?) - -> Nested Loop (actual rows=4 loops=1) - Output: metric.value, metric_name_local.name - Inner Unique: true - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_1.value - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) ORDER BY value ASC NULLS LAST - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) ORDER BY value ASC NULLS LAST - -> Index Scan using metric_name_local_pkey on public.metric_name_local (actual rows=1 loops=4) - Output: metric_name_local.id, metric_name_local.name - Index Cond: (metric_name_local.id = metric.id) -(24 rows) - --- Check returned types -SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -LOG: statement: SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; -DEBUG: try to push down a join on a reference table - pg_typeof | pg_typeof | pg_typeof | name | id | value ------------+-----------+------------------+------+----+------- - text | integer | double precision | cpu1 | 1 | 50 -(1 row) - --- Left join and reference table on the left hypertable on the right (no pushdown) -:PREFIX -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - Join Filter: (metric_name.id = metric.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Right join reference table on the left, hypertable on the right (can be converted into a left join by PostgreSQL, pushdown) -:PREFIX -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=4 loops=1) - Output: metric.id, metric_name.name, metric.ts, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.name, metric.id, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.name, metric_1.id, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.name, r8.id, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.name, metric_2.id, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.name, r9.id, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(17 rows) - --- Right join hypertable on the left, reference table on the right (no pushdown) -:PREFIX -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: metric_name.id, metric.ts, metric.value, metric_name.name - Join Filter: (metric.id = metric_name.id) - Rows Removed by Join Filter: 4 - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.id, metric_name.name - Filter: (metric_name.name ~~ 'cpu%'::text) - -> Materialize (actual rows=4 loops=2) - Output: metric.ts, metric.value, metric.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) -(24 rows) - --- Inner join and reference table left, hypertable on the right (pushdown) -:PREFIX -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric_name.id, metric_name.name, metric.ts, metric.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_name.id, metric_name.name, metric_1.ts, metric_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r1.id, r1.name, r8.ts, r8.value FROM (public.metric r8 INNER JOIN public.metric_name r1 ON (((r1.id = r8.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_name.id, metric_name.name, metric_2.ts, metric_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r1.id, r1.name, r9.ts, r9.value FROM (public.metric r9 INNER JOIN public.metric_name r1 ON (((r1.id = r9.id)) AND ((r1.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, hypertable left, reference table right (pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on two tables, reference table left, hypertable right (pushdown) -:PREFIX -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.id, m2.value, m1.id, m1.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.id, m2_1.value, m1.id, m1.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r7.ts, r7.id, r7.value, r2.id, r2.name FROM (public.metric r7 INNER JOIN public.metric_name r2 ON (((r7.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r7, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.id, m2_2.value, m1.id, m1.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r8.ts, r8.id, r8.value, r2.id, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1]) -(15 rows) - --- Implicit join on three tables (no pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name, m3.id, m3.name - Inner Unique: true - Join Filter: (m1.id = m3.id) - Rows Removed by Join Filter: 1 - -> Nested Loop (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=1 loops=4) - Output: m2.id, m2.name - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.id, m2.name - -> Materialize (actual rows=1 loops=4) - Output: m3.id, m3.name - -> Seq Scan on public.metric_name m3 (actual rows=2 loops=1) - Output: m3.id, m3.name - Filter: (m3.name ~~ 'cpu%'::text) -(34 rows) - --- Left join on a DHT and a subselect on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a DHT and a subselect with filter on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; -DEBUG: try to push down a join on a reference table - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)) AND ((r4.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join on a subselect on a DHT and a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.ts, metric.id, metric.value, metric_name.id, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.ts, metric_1.id, metric_1.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r2.id, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.ts, metric_2.id, metric_2.value, metric_name.id, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r2.id, r2.name FROM (public.metric r10 INNER JOIN public.metric_name r2 ON (((r10.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Left join and hypertable on left and right (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; - QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - -> Custom Scan (DataNodeScan) on public.metric m1 (actual rows=1 loops=1) - Output: m1.id, m1.ts, m1.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) - -> Custom Scan (AsyncAppend) (actual rows=1 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=1 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=0 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) AND ((id = 2)) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) AND ((id = 2)) -(24 rows) - --- Left join and reference table on left and right -:PREFIX -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; - QUERY PLAN ------------------------------------------------------------------------ - Nested Loop Left Join (actual rows=2 loops=1) - Output: m1.id, m1.name, m2.name - Inner Unique: true - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 1 - -> Seq Scan on public.metric_name m1 (actual rows=2 loops=1) - Output: m1.id, m1.name - Filter: (m1.name ~~ 'cpu%'::text) - -> Materialize (actual rows=2 loops=2) - Output: m2.name, m2.id - -> Seq Scan on public.metric_name m2 (actual rows=2 loops=1) - Output: m2.name, m2.id -(12 rows) - --- Only aggregation no values needs to be transferred -:PREFIX -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Aggregate (actual rows=1 loops=1) - Output: count(*) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT NULL FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT NULL FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name ~~ 'cpu%'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(14 rows) - --- Lateral joins that can be converted into regular joins -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id = r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; -DEBUG: try to push down a join on a reference table - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value, m2.id, m2.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r9.ts, r9.id, r9.value, r4.id, r4.name FROM (public.metric r9 LEFT JOIN public.metric_name r4 ON (((r9.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value, m2.id, m2.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r10.ts, r10.id, r10.value, r4.id, r4.name FROM (public.metric r10 LEFT JOIN public.metric_name r4 ON (((r10.id > r4.id)))) WHERE _timescaledb_functions.chunks_in(r10, ARRAY[1]) -(15 rows) - --- Lateral join that can not be converted and pushed down -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value, m2.id, m2.name - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.ts, m1.id, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.ts, m1_1.id, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.ts, m1_2.id, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Limit (actual rows=0 loops=4) - Output: m2.id, m2.name - -> Sort (actual rows=0 loops=4) - Output: m2.id, m2.name - Sort Key: m2.name - Sort Method: quicksort - -> Seq Scan on public.metric_name m2 (actual rows=0 loops=4) - Output: m2.id, m2.name - Filter: (m1.id > m2.id) - Rows Removed by Filter: 2 -(27 rows) - --- Two left joins (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------- - Hash Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value, mn.name - Inner Unique: true - Hash Cond: (m1.id = mn.id) - -> Nested Loop Left Join (actual rows=10 loops=1) - Output: m1.id, m1.ts, m1.value, m2.ts, m2.value - Join Filter: (m1.id = m2.id) - Rows Removed by Join Filter: 6 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m1.id, m1.ts, m1.value - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m1_1 (actual rows=3 loops=1) - Output: m1_1.id, m1_1.ts, m1_1.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m1_2 (actual rows=1 loops=1) - Output: m1_2.id, m1_2.ts, m1_2.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=4 loops=4) - Output: m2.ts, m2.value, m2.id - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: m2.ts, m2.value, m2.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric m2_1 (actual rows=3 loops=1) - Output: m2_1.ts, m2_1.value, m2_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric m2_2 (actual rows=1 loops=1) - Output: m2_2.ts, m2_2.value, m2_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT ts, id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Hash (actual rows=2 loops=1) - Output: mn.name, mn.id - Buckets: 1024 Batches: 1 - -> Seq Scan on public.metric_name mn (actual rows=2 loops=1) - Output: mn.name, mn.id -(45 rows) - -------- --- Tests with shippable and non-shippable joins / EquivalenceClass --- See 'dist_param.sql' for an explanation of the used textin / int4out --- functions. -------- --- Shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Result (actual rows=4 loops=1) - Output: metric_name.name, metric.value - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric_name.name - -> Merge Append (actual rows=4 loops=1) - Sort Key: metric_name.name - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r8.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) ORDER BY r2.name ASC NULLS LAST - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON ((texteq(('cpu'::text || textin(int4out(r9.id))), r2.name)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) ORDER BY r2.name ASC NULLS LAST -(21 rows) - --- Non-shippable equality class join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Merge Join (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Merge Cond: ((concat('cpu', metric.id)) = metric_name.name) - -> Sort (actual rows=4 loops=1) - Output: metric.value, metric.id, (concat('cpu', metric.id)) - Sort Key: (concat('cpu', metric.id)) - Sort Method: quicksort - -> Result (actual rows=4 loops=1) - Output: metric.value, metric.id, concat('cpu', metric.id) - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Sort (actual rows=4 loops=1) - Output: metric_name.name - Sort Key: metric_name.name - Sort Method: quicksort - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(33 rows) - --- Non-shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; -DEBUG: try to push down a join on a reference table -DEBUG: join pushdown on reference table is not supported for the used query - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate (actual rows=2 loops=1) - Output: metric_name.name, max(metric.value), count(*) - Group Key: metric_name.name - -> Sort (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Sort Key: metric_name.name - Sort Method: quicksort - -> Nested Loop (actual rows=4 loops=1) - Output: metric_name.name, metric.value - Join Filter: texteq(concat('cpu', textin(int4out(metric.id))), metric_name.name) - Rows Removed by Join Filter: 4 - -> Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.value, metric.id - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) on public.metric metric_1 (actual rows=3 loops=1) - Output: metric_1.value, metric_1.id - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) on public.metric metric_2 (actual rows=1 loops=1) - Output: metric_2.value, metric_2.id - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT id, value FROM public.metric WHERE _timescaledb_functions.chunks_in(public.metric.*, ARRAY[1]) - -> Materialize (actual rows=2 loops=4) - Output: metric_name.name - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name -(30 rows) - -------- --- MERGE is supported in PG >= 15. Currently, it is not supported in TimescaleDB --- on distributed hypertables. Perform a MERGE here to check if the join pushdown --- can handle the MERGE command properly. ON_ERROR_STOP is disabled for this test. --- Older PostgreSQL versions report an error because MERGE is not supported. This --- will be ignored due to the setting. --- Commenting below test as error meesage is different on windows vs unix. --- Issue #5725 is opened to track it. -------- --- \set ON_ERROR_STOP 0 --- MERGE INTO metric as target_0 --- USING metric as input_0 --- inner join (select id from metric_name as input_1) as subq_0 --- ON (TRUE) --- ON target_0.id = input_0.id --- WHEN MATCHED --- THEN DO NOTHING --- WHEN NOT MATCHED --- THEN DO NOTHING; --- \set ON_ERROR_STOP 1 -------- --- Tests without enable_per_data_node_queries (no pushdown supported) -------- -SET timescaledb.enable_per_data_node_queries = false; -LOG: statement: SET timescaledb.enable_per_data_node_queries = false; -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); -LOG: statement: EXPLAIN (analyze, verbose, costs off, timing off, summary off) -SELECT * FROM metric LEFT JOIN metric_name USING (id); -DEBUG: join on reference table is not considered to be pushed down because 'enable_per_data_node_queries' GUC is disabled - QUERY PLAN -------------------------------------------------------------------------------------------------------------- - Nested Loop Left Join (actual rows=4 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value, metric_name.name - Inner Unique: true - Join Filter: (_dist_hyper_1_1_chunk.id = metric_name.id) - Rows Removed by Join Filter: 1 - -> Append (actual rows=4 loops=1) - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_1_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_1_chunk.id, _dist_hyper_1_1_chunk.ts, _dist_hyper_1_1_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_1_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_2_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_2_chunk.id, _dist_hyper_1_2_chunk.ts, _dist_hyper_1_2_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_2_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_3_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_3_chunk.id, _dist_hyper_1_3_chunk.ts, _dist_hyper_1_3_chunk.value - Data node: db_dist_ref_table_join_1 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_3_chunk - -> Foreign Scan on _timescaledb_internal._dist_hyper_1_4_chunk (actual rows=1 loops=1) - Output: _dist_hyper_1_4_chunk.id, _dist_hyper_1_4_chunk.ts, _dist_hyper_1_4_chunk.value - Data node: db_dist_ref_table_join_2 - Fetcher Type: Cursor - Remote SQL: SELECT ts, id, value FROM _timescaledb_internal._dist_hyper_1_4_chunk - -> Materialize (actual rows=1 loops=4) - Output: metric_name.name, metric_name.id - -> Seq Scan on public.metric_name (actual rows=2 loops=1) - Output: metric_name.name, metric_name.id -(30 rows) - -SET timescaledb.enable_per_data_node_queries = true; -LOG: statement: SET timescaledb.enable_per_data_node_queries = true; -------- --- Tests with empty reftable -------- -RESET client_min_messages; -LOG: statement: RESET client_min_messages; -TRUNCATE metric_name; -CALL distributed_exec($$TRUNCATE metric_name;$$); --- Left join -SELECT * FROM metric LEFT JOIN metric_name USING (id); - id | ts | value | name -----+------------------------------+-------+------ - 1 | Tue Feb 01 15:02:02 2022 PST | 50 | - 1 | Tue Dec 31 14:01:01 2019 PST | 60 | - 1 | Thu Mar 02 16:03:03 2000 PST | 70 | - 2 | Mon Apr 03 18:04:03 2000 PDT | 80 | -(4 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=4 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=4 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=3 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 LEFT JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=1 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 LEFT JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Inner join -SELECT * FROM metric JOIN metric_name USING (id); - id | ts | value | name -----+----+-------+------ -(0 rows) - -:PREFIX -SELECT * FROM metric JOIN metric_name USING (id); - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - --- Filter on the NULL column -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name IS NOT NULL; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name IS NOT NULL)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=0 loops=1) - Output: metric.id, metric.ts, metric.value, metric_name.name - -> Append (actual rows=0 loops=1) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_1.id, metric_1.ts, metric_1.value, metric_name.name - Data node: db_dist_ref_table_join_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk - Remote SQL: SELECT r8.id, r8.ts, r8.value, r2.name FROM (public.metric r8 INNER JOIN public.metric_name r2 ON (((r8.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r8, ARRAY[1, 2, 3]) - -> Custom Scan (DataNodeScan) (actual rows=0 loops=1) - Output: metric_2.id, metric_2.ts, metric_2.value, metric_name.name - Data node: db_dist_ref_table_join_2 - Fetcher Type: COPY - Chunks: _dist_hyper_1_4_chunk - Remote SQL: SELECT r9.id, r9.ts, r9.value, r2.name FROM (public.metric r9 INNER JOIN public.metric_name r2 ON (((r9.id = r2.id)) AND ((r2.name = 'cpu1'::text)))) WHERE _timescaledb_functions.chunks_in(r9, ARRAY[1]) -(15 rows) - -------- --- Drop reftable on DNs and check proper error reporting -------- -\set ON_ERROR_STOP 0 -CALL distributed_exec($$DROP table metric_name;$$); -SELECT * FROM metric LEFT JOIN metric_name USING (id); -ERROR: [db_dist_ref_table_join_1]: relation "public.metric_name" does not exist diff --git a/tsl/test/expected/dist_remote_error-13.out b/tsl/test/expected/dist_remote_error-13.out deleted file mode 120000 index a5ad1b0b8cb..00000000000 --- a/tsl/test/expected/dist_remote_error-13.out +++ /dev/null @@ -1 +0,0 @@ -dist_remote_error-14.out \ No newline at end of file diff --git a/tsl/test/expected/dist_remote_error-14.out b/tsl/test/expected/dist_remote_error-14.out deleted file mode 100644 index c9feb05a642..00000000000 --- a/tsl/test/expected/dist_remote_error-14.out +++ /dev/null @@ -1,433 +0,0 @@ --- 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 DATA_NODE_1 data_node_1 ---\set DATA_NODE_2 data_node_2 ---\set DATA_NODE_3 data_node_3 --- Set up the data nodes. -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\c :TEST_DBNAME :ROLE_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------------+------------------------+--------------+------------------+------------------- - db_dist_remote_error_1 | db_dist_remote_error_1 | t | t | t - db_dist_remote_error_2 | db_dist_remote_error_2 | t | t | t - db_dist_remote_error_3 | db_dist_remote_error_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Import setup file to data nodes. -\unset ECHO --- Disable SSL to get stable error output across versions. SSL adds some output --- that changed in PG 14. -set timescaledb.debug_enable_ssl to off; -set client_min_messages to error; -SET timescaledb.hide_data_node_name_in_errors = 'on'; --- A relatively big table on one data node -CREATE TABLE metrics_dist_remote_error(filler_1 int, filler_2 int, filler_3 int, time timestamptz NOT NULL, device_id int, v0 int, v1 int, v2 float, v3 float); -SELECT create_distributed_hypertable('metrics_dist_remote_error','time','device_id',3, - data_nodes => ARRAY[:'DATA_NODE_1']); - create_distributed_hypertable ----------------------------------------- - (1,public,metrics_dist_remote_error,t) -(1 row) - -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_1; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-01 0:00:00+0'::timestamptz,'2000-01-05 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_2; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-06 0:00:00+0'::timestamptz,'2000-01-12 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_3; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-13 0:00:00+0'::timestamptz,'2000-01-19 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ANALYZE metrics_dist_remote_error; --- The error messages vary wildly between the Postgres versions, dependent on --- the particular behavior of libqp in this or that case. The purpose of this --- test is not to solidify this accidental behavior, but to merely exercise the --- error handling code to make sure it doesn't have fatal errors. Unfortunately, --- there is no way to suppress error output from a psql script. -set client_min_messages to ERROR; -\set ON_ERROR_STOP off -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(16384, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 16384 rows, 16384 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Output: 1 - Data node: db_dist_remote_error_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(6 rows) - --- We don't test fatal errors here, because PG versions before 14 are unable to --- report them properly to the access node, so we get different errors in these --- versions. --- Now test the same with the cursor fetcher. -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Output: 1 - Data node: db_dist_remote_error_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(6 rows) - --- Now test the same with the prepared statement fetcher. -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Output: 1 - Data node: db_dist_remote_error_1 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(6 rows) - -reset timescaledb.remote_data_fetcher; --- Table with broken send for a data type. -create table metrics_dist_bs(like metrics_dist_remote_error); -alter table metrics_dist_bs alter column v0 type bs; -select table_name from create_distributed_hypertable('metrics_dist_bs', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_bs -(1 row) - -set timescaledb.enable_connection_binary_data to off; -insert into metrics_dist_bs - select * from metrics_dist_remote_error; -set timescaledb.enable_connection_binary_data to on; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_bs; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -drop table metrics_dist_bs; --- Table with broken receive for a data type. -create table metrics_dist_br(like metrics_dist_remote_error); -alter table metrics_dist_br alter column v0 type br; -select table_name from create_distributed_hypertable('metrics_dist_br', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_br -(1 row) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - hypertable_name | replication_factor ------------------+-------------------- - metrics_dist_br | 1 -(1 row) - --- Test that INSERT and COPY fail on data nodes. --- Note that we use the text format for the COPY input, so that the access node --- doesn't call `recv` and fail by itself. It's going to use binary format for --- transfer to data nodes regardless of the input format. -set timescaledb.dist_copy_transfer_format = 'binary'; --- First, create the reference. -\copy (select * from metrics_dist_remote_error) to 'dist_remote_error.text' with (format text); --- We have to test various interleavings of COPY and INSERT to check that --- one can recover from connection failure states introduced by another. -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen --- Fail at different points -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1023 rows, 1023 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1024 rows, 1024 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1025 rows, 1025 rows seen -reset timescaledb.debug_broken_sendrecv_error_after; --- Same with different replication factor -truncate metrics_dist_br; -select set_replication_factor('metrics_dist_br', 2); - set_replication_factor ------------------------- - -(1 row) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - hypertable_name | replication_factor ------------------+-------------------- - metrics_dist_br | 2 -(1 row) - -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1023 rows, 1023 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1024 rows, 1024 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1025 rows, 1025 rows seen --- Should succeed with text format for data transfer. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); --- Final check. -set timescaledb.enable_connection_binary_data = false; -select count(*) from metrics_dist_br; - count -------- - 22800 -(1 row) - -set timescaledb.enable_connection_binary_data = true; -reset timescaledb.debug_broken_sendrecv_error_after; -drop table metrics_dist_br; --- Table with sleepy receive for a data type, to improve coverage of the waiting --- code on the access node. -create table metrics_dist_sr(like metrics_dist_remote_error); -alter table metrics_dist_sr alter column v0 type sr; -select table_name from create_distributed_hypertable('metrics_dist_sr', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_sr -(1 row) - --- We're using sleepy recv function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.dist_copy_transfer_format = 'binary'; --- Test INSERT and COPY with slow data node. -\copy metrics_dist_sr from 'dist_remote_error.text' with (format text); -insert into metrics_dist_sr select * from metrics_dist_remote_error; -select count(*) from metrics_dist_sr; - count -------- - 45600 -(1 row) - -drop table metrics_dist_sr; --- Table with sleepy send for a data type, on one data node, to improve coverage --- of waiting in data fetchers. -create table metrics_dist_ss(like metrics_dist_remote_error); -alter table metrics_dist_ss alter column v0 type ss; -select table_name from create_distributed_hypertable('metrics_dist_ss', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_ss -(1 row) - --- Populate the table, using text COPY to avoid the sleepy stuff. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_ss from 'dist_remote_error.text' with (format text); --- We're using sleepy send function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: COPY - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: COPY - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: COPY - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - --- Incorrect int output, to cover the error handling in tuplefactory. -create table metrics_dist_io(like metrics_dist_remote_error); -alter table metrics_dist_io alter column v0 type io; -select table_name from create_distributed_hypertable('metrics_dist_io', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_io -(1 row) - --- Populate the table, using binary COPY to avoid the broken in4out. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -\copy metrics_dist_io from 'dist_remote_error.text' with (format text); --- For testing, force the text format to exerices our broken out function. -set timescaledb.enable_connection_binary_data = false; -set timescaledb.dist_copy_transfer_format = 'text'; -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: invalid input syntax for type integer: "surprise" -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: cannot use COPY fetcher because some of the column types do not have binary serialization -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: invalid input syntax for type integer: "surprise" --- cleanup -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_remote_error-15.out b/tsl/test/expected/dist_remote_error-15.out deleted file mode 100644 index e1c4239193b..00000000000 --- a/tsl/test/expected/dist_remote_error-15.out +++ /dev/null @@ -1,436 +0,0 @@ --- 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 DATA_NODE_1 data_node_1 ---\set DATA_NODE_2 data_node_2 ---\set DATA_NODE_3 data_node_3 --- Set up the data nodes. -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\c :TEST_DBNAME :ROLE_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------------+------------------------+--------------+------------------+------------------- - db_dist_remote_error_1 | db_dist_remote_error_1 | t | t | t - db_dist_remote_error_2 | db_dist_remote_error_2 | t | t | t - db_dist_remote_error_3 | db_dist_remote_error_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Import setup file to data nodes. -\unset ECHO --- Disable SSL to get stable error output across versions. SSL adds some output --- that changed in PG 14. -set timescaledb.debug_enable_ssl to off; -set client_min_messages to error; -SET timescaledb.hide_data_node_name_in_errors = 'on'; --- A relatively big table on one data node -CREATE TABLE metrics_dist_remote_error(filler_1 int, filler_2 int, filler_3 int, time timestamptz NOT NULL, device_id int, v0 int, v1 int, v2 float, v3 float); -SELECT create_distributed_hypertable('metrics_dist_remote_error','time','device_id',3, - data_nodes => ARRAY[:'DATA_NODE_1']); - create_distributed_hypertable ----------------------------------------- - (1,public,metrics_dist_remote_error,t) -(1 row) - -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_1; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-01 0:00:00+0'::timestamptz,'2000-01-05 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_2; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-06 0:00:00+0'::timestamptz,'2000-01-12 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_3; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-13 0:00:00+0'::timestamptz,'2000-01-19 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ANALYZE metrics_dist_remote_error; --- The error messages vary wildly between the Postgres versions, dependent on --- the particular behavior of libqp in this or that case. The purpose of this --- test is not to solidify this accidental behavior, but to merely exercise the --- error handling code to make sure it doesn't have fatal errors. Unfortunately, --- there is no way to suppress error output from a psql script. -set client_min_messages to ERROR; -\set ON_ERROR_STOP off -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(16384, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 16384 rows, 16384 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=22799 loops=1) - Output: 1 - -> Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Data node: db_dist_remote_error_1 - Fetcher Type: COPY - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(7 rows) - --- We don't test fatal errors here, because PG versions before 14 are unable to --- report them properly to the access node, so we get different errors in these --- versions. --- Now test the same with the cursor fetcher. -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=22799 loops=1) - Output: 1 - -> Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Data node: db_dist_remote_error_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(7 rows) - --- Now test the same with the prepared statement fetcher. -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 0 rows, 0 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 701 rows, 701 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; -ERROR: []: debug point: requested to error out after 10000 rows, 10000 rows seen -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Result (actual rows=22799 loops=1) - Output: 1 - -> Custom Scan (DataNodeScan) on public.metrics_dist_remote_error (actual rows=22799 loops=1) - Data node: db_dist_remote_error_1 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_1_1_chunk, _dist_hyper_1_2_chunk, _dist_hyper_1_3_chunk, _dist_hyper_1_4_chunk, _dist_hyper_1_5_chunk, _dist_hyper_1_6_chunk, _dist_hyper_1_7_chunk, _dist_hyper_1_8_chunk, _dist_hyper_1_9_chunk - Remote SQL: SELECT NULL FROM public.metrics_dist_remote_error WHERE _timescaledb_functions.chunks_in(public.metrics_dist_remote_error.*, ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9]) AND ((public.ts_debug_shippable_error_after_n_rows(10000000, device_id) <> 0)) -(7 rows) - -reset timescaledb.remote_data_fetcher; --- Table with broken send for a data type. -create table metrics_dist_bs(like metrics_dist_remote_error); -alter table metrics_dist_bs alter column v0 type bs; -select table_name from create_distributed_hypertable('metrics_dist_bs', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_bs -(1 row) - -set timescaledb.enable_connection_binary_data to off; -insert into metrics_dist_bs - select * from metrics_dist_remote_error; -set timescaledb.enable_connection_binary_data to on; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_bs; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -drop table metrics_dist_bs; --- Table with broken receive for a data type. -create table metrics_dist_br(like metrics_dist_remote_error); -alter table metrics_dist_br alter column v0 type br; -select table_name from create_distributed_hypertable('metrics_dist_br', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_br -(1 row) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - hypertable_name | replication_factor ------------------+-------------------- - metrics_dist_br | 1 -(1 row) - --- Test that INSERT and COPY fail on data nodes. --- Note that we use the text format for the COPY input, so that the access node --- doesn't call `recv` and fail by itself. It's going to use binary format for --- transfer to data nodes regardless of the input format. -set timescaledb.dist_copy_transfer_format = 'binary'; --- First, create the reference. -\copy (select * from metrics_dist_remote_error) to 'dist_remote_error.text' with (format text); --- We have to test various interleavings of COPY and INSERT to check that --- one can recover from connection failure states introduced by another. -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen --- Fail at different points -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1023 rows, 1023 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1024 rows, 1024 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1025 rows, 1025 rows seen -reset timescaledb.debug_broken_sendrecv_error_after; --- Same with different replication factor -truncate metrics_dist_br; -select set_replication_factor('metrics_dist_br', 2); - set_replication_factor ------------------------- - -(1 row) - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - hypertable_name | replication_factor ------------------+-------------------- - metrics_dist_br | 2 -(1 row) - -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -insert into metrics_dist_br select * from metrics_dist_remote_error; -ERROR: []: debug point: requested to error out after 7103 rows, 7103 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1 rows, 1 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 2 rows, 2 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1023 rows, 1023 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1024 rows, 1024 rows seen -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -ERROR: []: debug point: requested to error out after 1025 rows, 1025 rows seen --- Should succeed with text format for data transfer. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); --- Final check. -set timescaledb.enable_connection_binary_data = false; -select count(*) from metrics_dist_br; - count -------- - 22800 -(1 row) - -set timescaledb.enable_connection_binary_data = true; -reset timescaledb.debug_broken_sendrecv_error_after; -drop table metrics_dist_br; --- Table with sleepy receive for a data type, to improve coverage of the waiting --- code on the access node. -create table metrics_dist_sr(like metrics_dist_remote_error); -alter table metrics_dist_sr alter column v0 type sr; -select table_name from create_distributed_hypertable('metrics_dist_sr', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_sr -(1 row) - --- We're using sleepy recv function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.dist_copy_transfer_format = 'binary'; --- Test INSERT and COPY with slow data node. -\copy metrics_dist_sr from 'dist_remote_error.text' with (format text); -insert into metrics_dist_sr select * from metrics_dist_remote_error; -select count(*) from metrics_dist_sr; - count -------- - 45600 -(1 row) - -drop table metrics_dist_sr; --- Table with sleepy send for a data type, on one data node, to improve coverage --- of waiting in data fetchers. -create table metrics_dist_ss(like metrics_dist_remote_error); -alter table metrics_dist_ss alter column v0 type ss; -select table_name from create_distributed_hypertable('metrics_dist_ss', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_ss -(1 row) - --- Populate the table, using text COPY to avoid the sleepy stuff. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_ss from 'dist_remote_error.text' with (format text); --- We're using sleepy send function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: Prepared statement - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: COPY - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: COPY - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: COPY - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (AsyncAppend) (actual rows=22800 loops=1) - Output: metrics_dist_ss."time", metrics_dist_ss.device_id, metrics_dist_ss.v0, metrics_dist_ss.v1, metrics_dist_ss.v2, metrics_dist_ss.v3 - -> Append (actual rows=22800 loops=1) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_1 (actual rows=4560 loops=1) - Output: metrics_dist_ss_1."time", metrics_dist_ss_1.device_id, metrics_dist_ss_1.v0, metrics_dist_ss_1.v1, metrics_dist_ss_1.v2, metrics_dist_ss_1.v3 - Data node: db_dist_remote_error_1 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_123_chunk, _dist_hyper_5_126_chunk, _dist_hyper_5_129_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[57, 58, 59]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_2 (actual rows=13680 loops=1) - Output: metrics_dist_ss_2."time", metrics_dist_ss_2.device_id, metrics_dist_ss_2.v0, metrics_dist_ss_2.v1, metrics_dist_ss_2.v2, metrics_dist_ss_2.v3 - Data node: db_dist_remote_error_2 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_124_chunk, _dist_hyper_5_127_chunk, _dist_hyper_5_130_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[49, 50, 51]) - -> Custom Scan (DataNodeScan) on public.metrics_dist_ss metrics_dist_ss_3 (actual rows=4560 loops=1) - Output: metrics_dist_ss_3."time", metrics_dist_ss_3.device_id, metrics_dist_ss_3.v0, metrics_dist_ss_3.v1, metrics_dist_ss_3.v2, metrics_dist_ss_3.v3 - Data node: db_dist_remote_error_3 - Fetcher Type: Cursor - Chunks: _dist_hyper_5_125_chunk, _dist_hyper_5_128_chunk, _dist_hyper_5_131_chunk - Remote SQL: SELECT "time", device_id, v0, v1, v2, v3 FROM public.metrics_dist_ss WHERE _timescaledb_functions.chunks_in(public.metrics_dist_ss.*, ARRAY[38, 39, 40]) -(21 rows) - --- Incorrect int output, to cover the error handling in tuplefactory. -create table metrics_dist_io(like metrics_dist_remote_error); -alter table metrics_dist_io alter column v0 type io; -select table_name from create_distributed_hypertable('metrics_dist_io', - 'time', 'device_id'); - table_name ------------------ - metrics_dist_io -(1 row) - --- Populate the table, using binary COPY to avoid the broken in4out. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -\copy metrics_dist_io from 'dist_remote_error.text' with (format text); --- For testing, force the text format to exerices our broken out function. -set timescaledb.enable_connection_binary_data = false; -set timescaledb.dist_copy_transfer_format = 'text'; -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: invalid input syntax for type integer: "surprise" -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: cannot use COPY fetcher because some of the column types do not have binary serialization -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; -ERROR: invalid input syntax for type integer: "surprise" --- cleanup -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_triggers.out b/tsl/test/expected/dist_triggers.out deleted file mode 100644 index e7497ebf889..00000000000 --- a/tsl/test/expected/dist_triggers.out +++ /dev/null @@ -1,733 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -psql:include/filter_exec.sql:5: NOTICE: schema "test" already exists, skipping -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ---------------------+--------------------+--------------+------------------+------------------- - db_dist_triggers_1 | db_dist_triggers_1 | t | t | t - db_dist_triggers_2 | db_dist_triggers_2 | t | t | t - db_dist_triggers_3 | db_dist_triggers_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Import testsupport.sql file to data nodes -\unset ECHO -SET ROLE :ROLE_1; -CREATE TABLE hyper ( - time BIGINT NOT NULL, - device_id TEXT NOT NULL, - sensor_1 NUMERIC NULL DEFAULT 1 -); --- Table to log trigger events -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - INSERT INTO public.trigger_events VALUES (TG_WHEN, TG_LEVEL, TG_OP, TG_NAME); - RETURN NEW; -END -$BODY$; -CALL distributed_exec($$ -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); -$$, ARRAY[:'DATA_NODE_1']); --- row triggers: BEFORE -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_update - BEFORE UPDATE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_delete - BEFORE DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER z_test_trigger_all - BEFORE INSERT OR UPDATE OR DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); --- row triggers: AFTER -CREATE TRIGGER _0_test_trigger_insert_after - AFTER INSERT ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_insert_after_when_dev1 - AFTER INSERT ON hyper - FOR EACH ROW - WHEN (NEW.device_id = 'dev1') - EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_update_after - AFTER UPDATE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_delete_after - AFTER DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER z_test_trigger_all_after - AFTER INSERT OR UPDATE OR DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); ---- Create some triggers before we turn the table into a distributed ---- hypertable and some triggers after so that we test both cases. -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device_id', 3, chunk_time_interval => 10, data_nodes => ARRAY[:'DATA_NODE_1', :'DATA_NODE_2']); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | hyper | t -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension_partition -ORDER BY 1,2; - dimension_id | range_start | data_nodes ---------------+----------------------+---------------------- - 2 | -9223372036854775808 | {db_dist_triggers_1} - 2 | 715827882 | {db_dist_triggers_2} - 2 | 1431655764 | {db_dist_triggers_1} -(3 rows) - --- FAILURE cases -\set ON_ERROR_STOP 0 --- Check that CREATE TRIGGER fails if a trigger already exists on a data node. -CALL distributed_exec($$ -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -$$, ARRAY[:'DATA_NODE_1']); -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -ERROR: [db_dist_triggers_1]: trigger "_0_test_trigger_insert_s_before" for relation "hyper" already exists -CALL distributed_exec($$ -DROP TRIGGER _0_test_trigger_insert_s_before ON hyper; -$$, ARRAY[:'DATA_NODE_1']); --- Test that trigger execution fails if trigger_events table doesn't --- exist on all nodes. Insert should fail -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); -ERROR: [db_dist_triggers_2]: relation "public.trigger_events" does not exist -\set ON_ERROR_STOP 1 --- Now, create trigger_events on the other nodes -CALL distributed_exec($$ -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); -$$, ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); --- Test that trigger fails if the user isn't the owner of the trigger --- function on one of the nodes. -RESET ROLE; -CALL distributed_exec($$ - ALTER FUNCTION test_trigger OWNER TO current_user; -$$, ARRAY[:'DATA_NODE_1']); -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Insert should fail since the trigger function on DN1 isn't owned by --- the user. -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); -\set ON_ERROR_STOP 1 --- Reset the owner of the trigger function on DN1 to the non-superuser -RESET ROLE; -CALL distributed_exec('ALTER FUNCTION test_trigger OWNER TO ' || :'ROLE_1', ARRAY[:'DATA_NODE_1']); -SET ROLE :ROLE_1; --- Add more triggers after the distributed hypertable is created --- statement triggers: BEFORE -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_update_s_before - BEFORE UPDATE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_delete_s_before - BEFORE DELETE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); --- statement triggers: AFTER -CREATE TRIGGER _0_test_trigger_insert_s_after - AFTER INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_update_s_after - AFTER UPDATE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -CREATE TRIGGER _0_test_trigger_delete_s_after - AFTER DELETE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); ---test triggers before create_distributed_hypertable -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); --- Show trigger count on access node. Only statement-level triggers --- fire on the access node. -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; - tg_when | tg_level | tg_op | tg_name | count ----------+-----------+--------+---------------------------------+------- - AFTER | STATEMENT | INSERT | _0_test_trigger_insert_s_after | 1 - BEFORE | STATEMENT | INSERT | _0_test_trigger_insert_s_before | 1 -(2 rows) - --- Show trigger counts on data nodes. Both statement-level and --- row-level triggers fire on the data nodes. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_1]: -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4 -NOTICE: [db_dist_triggers_1]: -tg_when|tg_level|tg_op|tg_name|count --------+--------+-----+-------+----- -(0 rows) - - -NOTICE: [db_dist_triggers_2]: -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4 -NOTICE: [db_dist_triggers_2]: -tg_when|tg_level |tg_op |tg_name |count --------+---------+------+--------------------------------------+----- -AFTER |ROW |INSERT|_0_test_trigger_insert_after | 2 -AFTER |ROW |INSERT|_0_test_trigger_insert_after_when_dev1| 2 -AFTER |ROW |INSERT|z_test_trigger_all_after | 2 -AFTER |STATEMENT|INSERT|_0_test_trigger_insert_s_after | 1 -BEFORE |ROW |INSERT|_0_test_trigger_insert | 2 -BEFORE |ROW |INSERT|z_test_trigger_all | 2 -BEFORE |STATEMENT|INSERT|_0_test_trigger_insert_s_before | 1 -(7 rows) - - - remote_exec -------------- - -(1 row) - -TRUNCATE trigger_events; -CALL distributed_exec($$ -TRUNCATE trigger_events; -$$); -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987700000000000, 'dev2', 1), (1257987800000000000, 'dev2', 1); -UPDATE hyper SET sensor_1 = 2; -DELETE FROM hyper; -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; - tg_when | tg_level | tg_op | tg_name | count ----------+-----------+--------+---------------------------------+------- - AFTER | STATEMENT | DELETE | _0_test_trigger_delete_s_after | 1 - AFTER | STATEMENT | INSERT | _0_test_trigger_insert_s_after | 1 - AFTER | STATEMENT | UPDATE | _0_test_trigger_update_s_after | 1 - BEFORE | STATEMENT | DELETE | _0_test_trigger_delete_s_before | 1 - BEFORE | STATEMENT | INSERT | _0_test_trigger_insert_s_before | 1 - BEFORE | STATEMENT | UPDATE | _0_test_trigger_update_s_before | 1 -(6 rows) - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_1]: -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4 -NOTICE: [db_dist_triggers_1]: -tg_when|tg_level |tg_op |tg_name |count --------+---------+------+-------------------------------+----- -AFTER |ROW |INSERT|_0_test_trigger_insert_after | 2 -AFTER |ROW |INSERT|z_test_trigger_all_after | 2 -AFTER |ROW |UPDATE|_0_test_trigger_update_after | 2 -AFTER |ROW |UPDATE|z_test_trigger_all_after | 2 -AFTER |STATEMENT|INSERT|_0_test_trigger_insert_s_after | 2 -BEFORE |ROW |DELETE|_0_test_trigger_delete | 2 -BEFORE |ROW |INSERT|_0_test_trigger_insert | 2 -BEFORE |ROW |INSERT|z_test_trigger_all | 2 -BEFORE |ROW |UPDATE|_0_test_trigger_update | 2 -BEFORE |ROW |UPDATE|z_test_trigger_all | 2 -BEFORE |STATEMENT|INSERT|_0_test_trigger_insert_s_before| 2 -(11 rows) - - -NOTICE: [db_dist_triggers_2]: -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4 -NOTICE: [db_dist_triggers_2]: -tg_when|tg_level|tg_op |tg_name |count --------+--------+------+----------------------------+----- -AFTER |ROW |UPDATE|_0_test_trigger_update_after| 2 -AFTER |ROW |UPDATE|z_test_trigger_all_after | 2 -BEFORE |ROW |DELETE|_0_test_trigger_delete | 2 -BEFORE |ROW |UPDATE|_0_test_trigger_update | 2 -BEFORE |ROW |UPDATE|z_test_trigger_all | 2 -(5 rows) - - - remote_exec -------------- - -(1 row) - --- Attach a new data node and show that the hypertable is created on --- the node, including its triggers. -SELECT attach_data_node(:'DATA_NODE_3', 'hyper'); -WARNING: attaching data node is deprecated - attach_data_node --------------------------- - (1,1,db_dist_triggers_3) -(1 row) - -SELECT * FROM _timescaledb_catalog.dimension_partition -ORDER BY 1,2; - dimension_id | range_start | data_nodes ---------------+----------------------+---------------------- - 2 | -9223372036854775808 | {db_dist_triggers_1} - 2 | 715827882 | {db_dist_triggers_2} - 2 | 1431655764 | {db_dist_triggers_3} -(3 rows) - --- Show that triggers are created on the new data node after attaching -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], -$$ - SELECT test.show_triggers('hyper'); -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_3]: - SELECT test.show_triggers('hyper') -NOTICE: [db_dist_triggers_3]: -show_triggers ------------------------------------------------------------ -(_0_test_trigger_delete,11,test_trigger) -(_0_test_trigger_delete_after,9,test_trigger) -(_0_test_trigger_delete_s_after,8,test_trigger) -(_0_test_trigger_delete_s_before,10,test_trigger) -(_0_test_trigger_insert,7,test_trigger) -(_0_test_trigger_insert_after,5,test_trigger) -(_0_test_trigger_insert_after_when_dev1,5,test_trigger) -(_0_test_trigger_insert_s_after,4,test_trigger) -(_0_test_trigger_insert_s_before,6,test_trigger) -(_0_test_trigger_update,19,test_trigger) -(_0_test_trigger_update_after,17,test_trigger) -(_0_test_trigger_update_s_after,16,test_trigger) -(_0_test_trigger_update_s_before,18,test_trigger) -(ts_insert_blocker,7,_timescaledb_functions.insert_blocker) -(z_test_trigger_all,31,test_trigger) -(z_test_trigger_all_after,29,test_trigger) -(16 rows) - - - remote_exec -------------- - -(1 row) - --- Insert data on the new data node to create a chunk and fire --- triggers. -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987700000000000, 'dev4', 1); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_3]: -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4 -NOTICE: [db_dist_triggers_3]: -tg_when|tg_level |tg_op |tg_name |count --------+---------+------+-------------------------------+----- -AFTER |ROW |INSERT|_0_test_trigger_insert_after | 1 -AFTER |ROW |INSERT|z_test_trigger_all_after | 1 -AFTER |STATEMENT|INSERT|_0_test_trigger_insert_s_after | 1 -BEFORE |ROW |INSERT|_0_test_trigger_insert | 1 -BEFORE |ROW |INSERT|z_test_trigger_all | 1 -BEFORE |STATEMENT|INSERT|_0_test_trigger_insert_s_before| 1 -(6 rows) - - - remote_exec -------------- - -(1 row) - ---test drop trigger -DROP TRIGGER _0_test_trigger_insert ON hyper; -DROP TRIGGER _0_test_trigger_insert_s_before ON hyper; -DROP TRIGGER _0_test_trigger_insert_after ON hyper; -DROP TRIGGER _0_test_trigger_insert_s_after ON hyper; -DROP TRIGGER _0_test_trigger_update ON hyper; -DROP TRIGGER _0_test_trigger_update_s_before ON hyper; -DROP TRIGGER _0_test_trigger_update_after ON hyper; -DROP TRIGGER _0_test_trigger_update_s_after ON hyper; -DROP TRIGGER _0_test_trigger_delete ON hyper; -DROP TRIGGER _0_test_trigger_delete_s_before ON hyper; -DROP TRIGGER _0_test_trigger_delete_after ON hyper; -DROP TRIGGER _0_test_trigger_delete_s_after ON hyper; -DROP TRIGGER z_test_trigger_all ON hyper; -DROP TRIGGER z_test_trigger_all_after ON hyper; -DROP TRIGGER _0_test_trigger_insert_after_when_dev1 ON hyper; --- Triggers are dropped on all data nodes: -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('hyper') st; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_1]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('hyper') st -NOTICE: [db_dist_triggers_1]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - -NOTICE: [db_dist_triggers_2]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('hyper') st -NOTICE: [db_dist_triggers_2]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - -NOTICE: [db_dist_triggers_3]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('hyper') st -NOTICE: [db_dist_triggers_3]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - - remote_exec -------------- - -(1 row) - --- Test triggers that modify tuples and make sure RETURNING is done --- properly (i.e., the modified tuple is returned). --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with custom insert nodes. -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -WARNING: distributed hypertable is deprecated - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | disttable | t -(1 row) - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -INSERT INTO datatable (id, time, device, temp_c) VALUES - (1, '2017-01-01 06:01', 1, 1), - (2, '2017-01-01 09:11', 3, 2), - (3, '2017-01-01 08:01', 1, 3), - (4, '2017-01-02 08:01', 2, 4), - (5, '2018-07-02 08:01', 87, 5), - (6, '2018-07-01 06:01', 13, 6), - (7, '2018-07-01 09:11', 90, 7), - (8, '2018-07-01 08:01', 29, 8); -CREATE OR REPLACE FUNCTION temp_increment_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - IF TG_OP = 'INSERT' THEN - NEW.temp_c = NEW.temp_c+1.0; - END IF; - RETURN NEW; -END -$BODY$; --- Add a BEFORE INSERT trigger to see that plan reverts to --- DataNodeDispatch when using RETURNING -CREATE TRIGGER _0_temp_increment - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION temp_increment_trigger(); --- Show that the trigger exists on a data node -SELECT test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT test.show_triggers('disttable') $$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_3]: SELECT test.show_triggers('disttable') -NOTICE: [db_dist_triggers_3]: -show_triggers ------------------------------------------------------------ -(_0_temp_increment,7,temp_increment_trigger) -(ts_insert_blocker,7,_timescaledb_functions.insert_blocker) -(2 rows) - - - remote_exec -------------- - -(1 row) - -TRUNCATE disttable; --- Show EXPLAINs for INSERT first with DataNodeCopy disabled. Should --- always use DataNodeDispatch -SET timescaledb.enable_distributed_insert_with_copy=false; --- Without RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ - Custom Scan (HypertableModify) (cost=0.00..33.55 rows=1570 width=24) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_triggers_1, db_dist_triggers_2, db_dist_triggers_3 - -> Insert on public.disttable (cost=0.00..33.55 rows=1570 width=24) - -> Custom Scan (DataNodeDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable(id, "time", device, temp_c) VALUES ($1, $2, $3, $4), ..., ($3997, $3998, $3999, $4000) - -> Custom Scan (ChunkDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..33.55 rows=1570 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(12 rows) - --- With RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..33.55 rows=1570 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - Insert on distributed hypertable public.disttable - Data nodes: db_dist_triggers_1, db_dist_triggers_2, db_dist_triggers_3 - -> Insert on public.disttable (cost=0.00..33.55 rows=1570 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - -> Custom Scan (DataNodeDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable(id, "time", device, temp_c) VALUES ($1, $2, $3, $4), ..., ($3997, $3998, $3999, $4000) RETURNING id, "time", device, temp_c - -> Custom Scan (ChunkDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..33.55 rows=1570 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(14 rows) - --- With DataNodeCopy enabled, should use DataNodeCopy when there's no --- RETURNING clause, but with RETURNING it should use DataNodeDispatch --- due to the modifying trigger. -SET timescaledb.enable_distributed_insert_with_copy=true; --- Without RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..33.55 rows=1570 width=24) - Insert on distributed hypertable public.disttable - Data nodes: db_dist_triggers_1, db_dist_triggers_2, db_dist_triggers_3 - -> Insert on public.disttable (cost=0.00..33.55 rows=1570 width=24) - -> Custom Scan (DataNodeCopy) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Remote SQL: COPY public.disttable (id, "time", device, temp_c) FROM STDIN WITH (FORMAT binary) - -> Custom Scan (ChunkDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..33.55 rows=1570 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(11 rows) - --- With RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable RETURNING *; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Custom Scan (HypertableModify) (cost=0.00..33.55 rows=1570 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - Insert on distributed hypertable public.disttable - Data nodes: db_dist_triggers_1, db_dist_triggers_2, db_dist_triggers_3 - -> Insert on public.disttable (cost=0.00..33.55 rows=1570 width=24) - Output: disttable.id, disttable."time", disttable.device, disttable.temp_c - -> Custom Scan (DataNodeDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - Batch size: 1000 - Remote SQL: INSERT INTO public.disttable(id, "time", device, temp_c) VALUES ($1, $2, $3, $4), ..., ($3997, $3998, $3999, $4000) RETURNING id, "time", device, temp_c - -> Custom Scan (ChunkDispatch) (cost=0.00..33.55 rows=1570 width=24) - Output: ((nextval('disttable_id_seq'::regclass))::integer), datatable."time", datatable.device, datatable.temp_c - -> Seq Scan on public.datatable (cost=0.00..33.55 rows=1570 width=24) - Output: nextval('disttable_id_seq'::regclass), datatable."time", datatable.device, datatable.temp_c -(14 rows) - --- Do the actual INSERT, but wrap in CTE to ensure ordered output in --- order to avoid flakiness. The returned rows should have temp_c --- incremented by the trigger -WITH inserted AS ( - INSERT INTO disttable (time, device, temp_c) - SELECT time, device, temp_c FROM datatable RETURNING * -) SELECT * FROM inserted ORDER BY 1; - id | time | device | temp_c -----+------------------------------+--------+-------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 2 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 3 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 4 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 5 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 6 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 7 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 8 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 9 -(8 rows) - --- Show that the RETURNING rows are the same as those stored after --- INSERT. Expect temp_c to be incremented by one compared to the --- original data. -SELECT di.id, di.time, di.device, di.temp_c AS temp_c, da.temp_c AS temp_c_orig -FROM disttable di, datatable da -WHERE di.id = da.id -ORDER BY 1; - id | time | device | temp_c | temp_c_orig -----+------------------------------+--------+--------+------------- - 1 | Sun Jan 01 06:01:00 2017 PST | 1 | 2 | 1 - 2 | Sun Jan 01 09:11:00 2017 PST | 3 | 3 | 2 - 3 | Sun Jan 01 08:01:00 2017 PST | 1 | 4 | 3 - 4 | Mon Jan 02 08:01:00 2017 PST | 2 | 5 | 4 - 5 | Mon Jul 02 08:01:00 2018 PDT | 87 | 6 | 5 - 6 | Sun Jul 01 06:01:00 2018 PDT | 13 | 7 | 6 - 7 | Sun Jul 01 09:11:00 2018 PDT | 90 | 8 | 7 - 8 | Sun Jul 01 08:01:00 2018 PDT | 29 | 9 | 8 -(8 rows) - --- Rename a trigger -ALTER TRIGGER _0_temp_increment ON disttable RENAME TO _1_temp_increment; --- Show that remote chunks have the new trigger name -SELECT * FROM test.remote_exec(NULL, $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_1]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_1]: -chunk_relid |show_triggers --------------------------------------------+-------------------------------------------- -_timescaledb_internal._dist_hyper_2_6_chunk|(_1_temp_increment,7,temp_increment_trigger) -_timescaledb_internal._dist_hyper_2_9_chunk|(_1_temp_increment,7,temp_increment_trigger) -(2 rows) - - -NOTICE: [db_dist_triggers_2]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_2]: -chunk_relid |show_triggers ---------------------------------------------+-------------------------------------------- -_timescaledb_internal._dist_hyper_2_8_chunk |(_1_temp_increment,7,temp_increment_trigger) -_timescaledb_internal._dist_hyper_2_10_chunk|(_1_temp_increment,7,temp_increment_trigger) -(2 rows) - - -NOTICE: [db_dist_triggers_3]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_3]: -chunk_relid |show_triggers ---------------------------------------------+-------------------------------------------- -_timescaledb_internal._dist_hyper_2_7_chunk |(_1_temp_increment,7,temp_increment_trigger) -_timescaledb_internal._dist_hyper_2_11_chunk|(_1_temp_increment,7,temp_increment_trigger) -(2 rows) - - - remote_exec -------------- - -(1 row) - --- Drop the trigger and show that it is dropped on data nodes -DROP TRIGGER _1_temp_increment ON disttable; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; -$$); -WARNING: executing remote command is deprecated -NOTICE: [db_dist_triggers_1]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_1]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - -NOTICE: [db_dist_triggers_2]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_2]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - -NOTICE: [db_dist_triggers_3]: -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st -NOTICE: [db_dist_triggers_3]: -chunk_relid|show_triggers ------------+------------- -(0 rows) - - - remote_exec -------------- - -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_util-13.out b/tsl/test/expected/dist_util-13.out deleted file mode 100644 index 194f7eb33c1..00000000000 --- a/tsl/test/expected/dist_util-13.out +++ /dev/null @@ -1,1111 +0,0 @@ --- 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. ----------------------------------------------------------------- --- Test version compability function -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE OR REPLACE FUNCTION compatible_version(version CSTRING, reference CSTRING) -RETURNS BOOLEAN -AS :TSL_MODULE_PATHNAME, 'ts_test_compatible_version' -LANGUAGE C VOLATILE; -SELECT * FROM compatible_version('2.0.0-beta3.19', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.0', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.0', reference => '2.1.19-beta3.19'); - compatible_version --------------------- - t -(1 row) - --- These should not parse and instead generate an error. -\set ON_ERROR_STOP 0 -SELECT * FROM compatible_version('2.1.*', reference => '2.1.19-beta3.19'); -ERROR: invalid data node version 2.1.* -SELECT * FROM compatible_version('2.1.0', reference => '2.1.*'); -ERROR: invalid access node version 2.1.* -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Create two distributed databases -CREATE DATABASE frontend_1; -CREATE DATABASE frontend_2; -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '87c235e9-d857-4f16-b59f-7fbac9b87664' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_1_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_1_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(2 rows) - -SET client_min_messages TO NOTICE; --- Create a second frontend database and add a backend to it -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '77348176-09da-4a80-bc78-e31bdf5e63ec' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_2_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_2_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(2 rows) - -SET client_min_messages TO NOTICE; -\set ON_ERROR_STOP 0 ----------------------------------------------------------------- --- Adding frontend as backend to a different frontend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_2" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding backend from a different group as a backend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "backend_2_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding a valid backend target but to an existing backend should fail -\c backend_1_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database ----------------------------------------------------------------- --- Adding a frontend (frontend 1) as a backend to a nondistributed node (TEST_DBNAME) should fail -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Test that a data node can be moved to a different frontend if it is --- removed first. -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | t | t -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - --- Now remove a backend from this distributed database to add it to the other cluster -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM delete_data_node('data_node_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- dist_uuid should not be removed from the metadata on the data node, --- so we need to delete it manually before adding it to another --- backend. -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - key ------------ - dist_uuid -(1 row) - -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; --- Add the data node to the second frontend without bootstrapping -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => false); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | f | f -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - --- Test space reporting functions for distributed and non-distributed tables -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -CREATE TABLE nondisttable(time timestamptz, device int CHECK (device > 0), temp float); -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), temp float); -SELECT * FROM create_hypertable('nondisttable', 'time', create_default_indexes => false); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 1 | public | nondisttable | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable', 'time', create_default_indexes => false); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | disttable | t -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes -ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+--------------------+----------------+------------+---------------------+----------------+--------------------+---------------------------+------------- - public | disttable | cluster_super_user | 1 | 0 | f | t | 1 | {data_node_1,data_node_2} | - public | nondisttable | cluster_super_user | 1 | 0 | f | f | | | -(2 rows) - --- Test size functions on empty distributed hypertable. --- --- First, show the output from standard PG size functions. The --- functions are expected to remove 0 table bytes for the distributed --- hypertable since it doesn't have local storage. -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 0 | 0 | 0 | data_node_1 - 0 | 0 | 0 | 0 | data_node_2 - 0 | 0 | 0 | 0 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 0 | 0 | 0 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - --- Create primary key index and check how it affects the size of the --- empty hypertables. -ALTER TABLE nondisttable ADD CONSTRAINT nondisttable_pkey PRIMARY KEY (time); -ALTER TABLE disttable ADD CONSTRAINT disttable_pkey PRIMARY KEY (time); -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - --- Note that the empty disttable is three times the size of the --- nondisttable since it has primary key indexes on two data nodes in --- addition to the access node. -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 8192 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 8192 | 0 | 8192 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 8192 -(1 row) - --- Test size functions on tables with an empty chunk -INSERT INTO nondisttable VALUES ('2017-01-01 06:01', 1, 1.1); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 8192 | 8192 | 16384 | 24576 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 24576 | 8192 | 16384 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 49152 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 8192 | 24576 | 0 | 32768 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 8192 | 24576 | 0 | 32768 | -(1 row) - --- Delete all data, but keep chunks -DELETE FROM nondisttable; -DELETE FROM disttable; -VACUUM FULL ANALYZE nondisttable; -VACUUM FULL ANALYZE disttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size ----------------+------------------+----------------- - 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 16384 | 0 | 16384 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 16384 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 16384 | 0 | 16384 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 0 | 8192 | 0 | 8192 | data_node_1 -(1 row) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 16384 -(1 row) - --- Test size functions on non-empty hypertable -INSERT INTO nondisttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 08:01', 1, 1.2), - ('2018-01-02 08:01', 2, 1.3), - ('2019-01-01 09:11', 3, 2.1), - ('2017-01-01 06:05', 1, 1.4); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Enable compression -ALTER TABLE nondisttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -ALTER TABLE disttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 0 | | | | | | | | | data_node_1 - 1 | 0 | | | | | | | | | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 0 | | | | | | | | | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Uncompressed | | | | | | | | | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Uncompressed | | | | | | | | | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_3_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Compress two chunks (out of three) to see effect of compression -SELECT compress_chunk(ch) -FROM show_chunks('disttable') ch -LIMIT 2; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_2_2_chunk - _timescaledb_internal._dist_hyper_2_5_chunk -(2 rows) - -SELECT compress_chunk(ch) -FROM show_chunks('nondisttable') ch -LIMIT 2; - compress_chunk ----------------------------------------- - _timescaledb_internal._hyper_1_1_chunk - _timescaledb_internal._hyper_1_3_chunk -(2 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 114688 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 49152 | 8192 | 73728 | data_node_1 - 8192 | 32768 | 8192 | 49152 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 73728 | 16384 | 114688 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 24576 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 24576 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 24576 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 24576 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 16384 | 32768 | 16384 | 65536 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - --- Make sure functions work for non-superuser -CREATE TABLE size_test_table (value int); -INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000); -SET ROLE :ROLE_1; --- No query permissions -\set ON_ERROR_STOP 0 -SELECT count(*) FROM disttable; -ERROR: permission denied for table disttable -SELECT count(*) FROM size_test_table; -ERROR: permission denied for table size_test_table -\set ON_ERROR_STOP 1 --- Size functions work anyway, similar to pg_table_size, et al. --- pg_table_size() can vary with platform so not outputting -SELECT 1 FROM pg_table_size('size_test_table'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('disttable'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('nondisttable'); - ?column? ----------- - 1 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 114688 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 49152 | 8192 | 73728 | data_node_1 - 8192 | 32768 | 8192 | 49152 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 73728 | 16384 | 114688 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 24576 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 24576 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 24576 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 24576 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 16384 | 32768 | 16384 | 65536 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 8192 | 16384 | 8192 | 32768 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - -RESET ROLE; -GRANT SELECT ON disttable TO :ROLE_1; -GRANT SELECT ON nondisttable TO :ROLE_1; -SET ROLE :ROLE_1; --- Querying should now work -SELECT count(*) FROM disttable; - count -------- - 5 -(1 row) - --- hypertable_size should work now with SELECT privilege on tables -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 114688 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 49152 | 8192 | 73728 | data_node_1 - 8192 | 32768 | 8192 | 49152 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 73728 | 16384 | 114688 | -(1 row) - --- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser -\c :TEST_DBNAME :ROLE_1 -\unset ECHO -\set ON_ERROR_STOP 0 -SET timescaledb.ssl_dir TO 'ssldir'; -ERROR: parameter "timescaledb.ssl_dir" cannot be changed now -SET timescaledb.passfile TO 'passfile'; -ERROR: parameter "timescaledb.passfile" cannot be changed now -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -DROP DATABASE backend_1_1 WITH (FORCE); -DROP DATABASE backend_x_2 WITH (FORCE); -DROP DATABASE backend_2_1 WITH (FORCE); -DROP DATABASE frontend_1 WITH (FORCE); -DROP DATABASE frontend_2 WITH (FORCE); diff --git a/tsl/test/expected/dist_util-14.out b/tsl/test/expected/dist_util-14.out deleted file mode 100644 index 5aea91b7e40..00000000000 --- a/tsl/test/expected/dist_util-14.out +++ /dev/null @@ -1,1111 +0,0 @@ --- 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. ----------------------------------------------------------------- --- Test version compability function -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE OR REPLACE FUNCTION compatible_version(version CSTRING, reference CSTRING) -RETURNS BOOLEAN -AS :TSL_MODULE_PATHNAME, 'ts_test_compatible_version' -LANGUAGE C VOLATILE; -SELECT * FROM compatible_version('2.0.0-beta3.19', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.0', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.0', reference => '2.1.19-beta3.19'); - compatible_version --------------------- - t -(1 row) - --- These should not parse and instead generate an error. -\set ON_ERROR_STOP 0 -SELECT * FROM compatible_version('2.1.*', reference => '2.1.19-beta3.19'); -ERROR: invalid data node version 2.1.* -SELECT * FROM compatible_version('2.1.0', reference => '2.1.*'); -ERROR: invalid access node version 2.1.* -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Create two distributed databases -CREATE DATABASE frontend_1; -CREATE DATABASE frontend_2; -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '87c235e9-d857-4f16-b59f-7fbac9b87664' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_1_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_1_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(2 rows) - -SET client_min_messages TO NOTICE; --- Create a second frontend database and add a backend to it -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '77348176-09da-4a80-bc78-e31bdf5e63ec' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_2_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_2_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(2 rows) - -SET client_min_messages TO NOTICE; -\set ON_ERROR_STOP 0 ----------------------------------------------------------------- --- Adding frontend as backend to a different frontend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_2" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding backend from a different group as a backend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "backend_2_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding a valid backend target but to an existing backend should fail -\c backend_1_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database ----------------------------------------------------------------- --- Adding a frontend (frontend 1) as a backend to a nondistributed node (TEST_DBNAME) should fail -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Test that a data node can be moved to a different frontend if it is --- removed first. -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | t | t -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - --- Now remove a backend from this distributed database to add it to the other cluster -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM delete_data_node('data_node_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- dist_uuid should not be removed from the metadata on the data node, --- so we need to delete it manually before adding it to another --- backend. -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - key ------------ - dist_uuid -(1 row) - -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; --- Add the data node to the second frontend without bootstrapping -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => false); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | f | f -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - --- Test space reporting functions for distributed and non-distributed tables -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -CREATE TABLE nondisttable(time timestamptz, device int CHECK (device > 0), temp float); -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), temp float); -SELECT * FROM create_hypertable('nondisttable', 'time', create_default_indexes => false); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 1 | public | nondisttable | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable', 'time', create_default_indexes => false); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | disttable | t -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes -ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+--------------------+----------------+------------+---------------------+----------------+--------------------+---------------------------+------------- - public | disttable | cluster_super_user | 1 | 0 | f | t | 1 | {data_node_1,data_node_2} | - public | nondisttable | cluster_super_user | 1 | 0 | f | f | | | -(2 rows) - --- Test size functions on empty distributed hypertable. --- --- First, show the output from standard PG size functions. The --- functions are expected to remove 0 table bytes for the distributed --- hypertable since it doesn't have local storage. -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 0 | 0 | 0 | data_node_1 - 0 | 0 | 0 | 0 | data_node_2 - 0 | 0 | 0 | 0 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 0 | 0 | 0 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - --- Create primary key index and check how it affects the size of the --- empty hypertables. -ALTER TABLE nondisttable ADD CONSTRAINT nondisttable_pkey PRIMARY KEY (time); -ALTER TABLE disttable ADD CONSTRAINT disttable_pkey PRIMARY KEY (time); -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - --- Note that the empty disttable is three times the size of the --- nondisttable since it has primary key indexes on two data nodes in --- addition to the access node. -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 8192 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 8192 | 0 | 8192 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 8192 -(1 row) - --- Test size functions on tables with an empty chunk -INSERT INTO nondisttable VALUES ('2017-01-01 06:01', 1, 1.1); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 8192 | 8192 | 16384 | 24576 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 24576 | 8192 | 16384 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 49152 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 8192 | 24576 | 0 | 32768 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 8192 | 24576 | 0 | 32768 | -(1 row) - --- Delete all data, but keep chunks -DELETE FROM nondisttable; -DELETE FROM disttable; -VACUUM FULL ANALYZE nondisttable; -VACUUM FULL ANALYZE disttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size ----------------+------------------+----------------- - 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 16384 | 0 | 16384 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 16384 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 16384 | 0 | 16384 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 0 | 8192 | 0 | 8192 | data_node_1 -(1 row) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 16384 -(1 row) - --- Test size functions on non-empty hypertable -INSERT INTO nondisttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 08:01', 1, 1.2), - ('2018-01-02 08:01', 2, 1.3), - ('2019-01-01 09:11', 3, 2.1), - ('2017-01-01 06:05', 1, 1.4); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Enable compression -ALTER TABLE nondisttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -ALTER TABLE disttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 0 | | | | | | | | | data_node_1 - 1 | 0 | | | | | | | | | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 0 | | | | | | | | | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Uncompressed | | | | | | | | | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Uncompressed | | | | | | | | | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_3_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Compress two chunks (out of three) to see effect of compression -SELECT compress_chunk(ch) -FROM show_chunks('disttable') ch -LIMIT 2; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_2_2_chunk - _timescaledb_internal._dist_hyper_2_5_chunk -(2 rows) - -SELECT compress_chunk(ch) -FROM show_chunks('nondisttable') ch -LIMIT 2; - compress_chunk ----------------------------------------- - _timescaledb_internal._hyper_1_1_chunk - _timescaledb_internal._hyper_1_3_chunk -(2 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 16384 | 24576 | 8192 | 49152 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 16384 | 24576 | 8192 | 49152 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_3_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 32768 | 32768 | 16384 | 81920 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - --- Make sure functions work for non-superuser -CREATE TABLE size_test_table (value int); -INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000); -SET ROLE :ROLE_1; --- No query permissions -\set ON_ERROR_STOP 0 -SELECT count(*) FROM disttable; -ERROR: permission denied for table disttable -SELECT count(*) FROM size_test_table; -ERROR: permission denied for table size_test_table -\set ON_ERROR_STOP 1 --- Size functions work anyway, similar to pg_table_size, et al. --- pg_table_size() can vary with platform so not outputting -SELECT 1 FROM pg_table_size('size_test_table'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('disttable'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('nondisttable'); - ?column? ----------- - 1 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 16384 | 24576 | 8192 | 49152 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 16384 | 24576 | 8192 | 49152 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_3_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 32768 | 32768 | 16384 | 81920 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - -RESET ROLE; -GRANT SELECT ON disttable TO :ROLE_1; -GRANT SELECT ON nondisttable TO :ROLE_1; -SET ROLE :ROLE_1; --- Querying should now work -SELECT count(*) FROM disttable; - count -------- - 5 -(1 row) - --- hypertable_size should work now with SELECT privilege on tables -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - --- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser -\c :TEST_DBNAME :ROLE_1 -\unset ECHO -\set ON_ERROR_STOP 0 -SET timescaledb.ssl_dir TO 'ssldir'; -ERROR: parameter "timescaledb.ssl_dir" cannot be changed now -SET timescaledb.passfile TO 'passfile'; -ERROR: parameter "timescaledb.passfile" cannot be changed now -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -DROP DATABASE backend_1_1 WITH (FORCE); -DROP DATABASE backend_x_2 WITH (FORCE); -DROP DATABASE backend_2_1 WITH (FORCE); -DROP DATABASE frontend_1 WITH (FORCE); -DROP DATABASE frontend_2 WITH (FORCE); diff --git a/tsl/test/expected/dist_util-15.out b/tsl/test/expected/dist_util-15.out deleted file mode 100644 index 5aea91b7e40..00000000000 --- a/tsl/test/expected/dist_util-15.out +++ /dev/null @@ -1,1111 +0,0 @@ --- 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. ----------------------------------------------------------------- --- Test version compability function -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE OR REPLACE FUNCTION compatible_version(version CSTRING, reference CSTRING) -RETURNS BOOLEAN -AS :TSL_MODULE_PATHNAME, 'ts_test_compatible_version' -LANGUAGE C VOLATILE; -SELECT * FROM compatible_version('2.0.0-beta3.19', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.0', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0'); - compatible_version --------------------- - f -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.9', reference => '2.0.0-beta3.19'); - compatible_version --------------------- - t -(1 row) - -SELECT * FROM compatible_version('2.1.0', reference => '2.1.19-beta3.19'); - compatible_version --------------------- - t -(1 row) - --- These should not parse and instead generate an error. -\set ON_ERROR_STOP 0 -SELECT * FROM compatible_version('2.1.*', reference => '2.1.19-beta3.19'); -ERROR: invalid data node version 2.1.* -SELECT * FROM compatible_version('2.1.0', reference => '2.1.*'); -ERROR: invalid access node version 2.1.* -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Create two distributed databases -CREATE DATABASE frontend_1; -CREATE DATABASE frontend_2; -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '87c235e9-d857-4f16-b59f-7fbac9b87664' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_1_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_1_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(2 rows) - -SET client_min_messages TO NOTICE; --- Create a second frontend database and add a backend to it -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '77348176-09da-4a80-bc78-e31bdf5e63ec' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value -------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_2_1'); - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_1 | backend_2_1 | t | t | t -(1 row) - -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; - key | value ------------+-------------------------------------- - uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(2 rows) - -SET client_min_messages TO NOTICE; -\set ON_ERROR_STOP 0 ----------------------------------------------------------------- --- Adding frontend as backend to a different frontend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_2" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding backend from a different group as a backend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "backend_2_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node ----------------------------------------------------------------- --- Adding a valid backend target but to an existing backend should fail -\c backend_1_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: unable to assign data nodes from an existing distributed database ----------------------------------------------------------------- --- Adding a frontend (frontend 1) as a backend to a nondistributed node (TEST_DBNAME) should fail -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => true); -WARNING: adding data node is deprecated -NOTICE: database "frontend_1" already exists on data node, skipping -NOTICE: extension "timescaledb" already exists on data node, skipping -ERROR: cannot add "invalid_data_node" as a data node -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => false); -WARNING: adding data node is deprecated -ERROR: cannot add "invalid_data_node" as a data node -\set ON_ERROR_STOP 1 ----------------------------------------------------------------- --- Test that a data node can be moved to a different frontend if it is --- removed first. -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => true); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | t | t -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 87c235e9-d857-4f16-b59f-7fbac9b87664 -(1 row) - --- Now remove a backend from this distributed database to add it to the other cluster -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM delete_data_node('data_node_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - --- dist_uuid should not be removed from the metadata on the data node, --- so we need to delete it manually before adding it to another --- backend. -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - key ------------ - dist_uuid -(1 row) - -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; --- Add the data node to the second frontend without bootstrapping -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => false); -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created --------------+-------------+--------------+------------------+------------------- - data_node_2 | backend_x_2 | t | f | f -(1 row) - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - key | value ------------+-------------------------------------- - dist_uuid | 77348176-09da-4a80-bc78-e31bdf5e63ec -(1 row) - --- Test space reporting functions for distributed and non-distributed tables -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -CREATE TABLE nondisttable(time timestamptz, device int CHECK (device > 0), temp float); -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), temp float); -SELECT * FROM create_hypertable('nondisttable', 'time', create_default_indexes => false); -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+--------------+--------- - 1 | public | nondisttable | t -(1 row) - -SELECT * FROM create_distributed_hypertable('disttable', 'time', create_default_indexes => false); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 2 | public | disttable | t -(1 row) - -SELECT node_name FROM timescaledb_information.data_nodes -ORDER BY node_name; - node_name -------------- - data_node_1 - data_node_2 -(2 rows) - -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+--------------------+----------------+------------+---------------------+----------------+--------------------+---------------------------+------------- - public | disttable | cluster_super_user | 1 | 0 | f | t | 1 | {data_node_1,data_node_2} | - public | nondisttable | cluster_super_user | 1 | 0 | f | f | | | -(2 rows) - --- Test size functions on empty distributed hypertable. --- --- First, show the output from standard PG size functions. The --- functions are expected to remove 0 table bytes for the distributed --- hypertable since it doesn't have local storage. -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ -(0 rows) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----+------------+-----------+------------+------------ -(0 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 0 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 0 | 0 | 0 | data_node_1 - 0 | 0 | 0 | 0 | data_node_2 - 0 | 0 | 0 | 0 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 0 | 0 | 0 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - --- Create primary key index and check how it affects the size of the --- empty hypertables. -ALTER TABLE nondisttable ADD CONSTRAINT nondisttable_pkey PRIMARY KEY (time); -ALTER TABLE disttable ADD CONSTRAINT disttable_pkey PRIMARY KEY (time); -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - --- Note that the empty disttable is three times the size of the --- nondisttable since it has primary key indexes on two data nodes in --- addition to the access node. -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 8192 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 8192 | 0 | 8192 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ---------------+------------+-------------+-------------+-------------+-------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 24576 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 8192 -(1 row) - --- Test size functions on tables with an empty chunk -INSERT INTO nondisttable VALUES ('2017-01-01 06:01', 1, 1.1); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 8192 | 8192 | 16384 | 24576 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 24576 | 8192 | 16384 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 49152 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 8192 | 24576 | 0 | 32768 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 8192 | 24576 | 0 | 32768 | -(1 row) - --- Delete all data, but keep chunks -DELETE FROM nondisttable; -DELETE FROM disttable; -VACUUM FULL ANALYZE nondisttable; -VACUUM FULL ANALYZE disttable; -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch) -FROM show_chunks('disttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size ----------------+------------------+----------------- - 0 | 0 | 0 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('disttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size ----------------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._dist_hyper_2_2_chunk | 0 | 0 | 0 | 0 -(1 row) - -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; - pg_table_size | pg_relation_size | pg_indexes_size | pg_total_relation_size ----------------+------------------+-----------------+------------------------ - 0 | 0 | 8192 | 8192 -(1 row) - -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - total_size | heap_size | index_size | toast_size -------------+-----------+------------+------------ - 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - ch | total_size | heap_size | index_size | toast_size -----------------------------------------+------------+-----------+------------+------------ - _timescaledb_internal._hyper_1_1_chunk | 8192 | 0 | 8192 | 0 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 0 | 16384 | 0 | 16384 | data_node_1 - 0 | 8192 | 0 | 8192 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 16384 -(1 row) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 0 | 16384 | 0 | 16384 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 0 | 8192 | 0 | 8192 | data_node_1 -(1 row) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 0 | 8192 | 0 | 8192 | -(1 row) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 32768 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 16384 -(1 row) - --- Test size functions on non-empty hypertable -INSERT INTO nondisttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 08:01', 1, 1.2), - ('2018-01-02 08:01', 2, 1.3), - ('2019-01-01 09:11', 3, 2.1), - ('2017-01-01 06:05', 1, 1.4); -INSERT INTO disttable SELECT * FROM nondisttable; -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- -(0 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Enable compression -ALTER TABLE nondisttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -ALTER TABLE disttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 98304 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 81920 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 16384 | 40960 | 0 | 57344 | data_node_1 - 8192 | 24576 | 0 | 32768 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 24576 | 57344 | 0 | 81920 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 16384 | 0 | 24576 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_3_chunk | 8192 | 16384 | 0 | 24576 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 0 | | | | | | | | | data_node_1 - 1 | 0 | | | | | | | | | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 0 | | | | | | | | | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Uncompressed | | | | | | | | | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Uncompressed | | | | | | | | | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_3_chunk | Uncompressed | | | | | | | | | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 73728 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - --- Compress two chunks (out of three) to see effect of compression -SELECT compress_chunk(ch) -FROM show_chunks('disttable') ch -LIMIT 2; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_2_2_chunk - _timescaledb_internal._dist_hyper_2_5_chunk -(2 rows) - -SELECT compress_chunk(ch) -FROM show_chunks('nondisttable') ch -LIMIT 2; - compress_chunk ----------------------------------------- - _timescaledb_internal._hyper_1_1_chunk - _timescaledb_internal._hyper_1_3_chunk -(2 rows) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 16384 | 24576 | 8192 | 49152 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 16384 | 24576 | 8192 | 49152 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_3_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 32768 | 32768 | 16384 | 81920 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - --- Make sure functions work for non-superuser -CREATE TABLE size_test_table (value int); -INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000); -SET ROLE :ROLE_1; --- No query permissions -\set ON_ERROR_STOP 0 -SELECT count(*) FROM disttable; -ERROR: permission denied for table disttable -SELECT count(*) FROM size_test_table; -ERROR: permission denied for table size_test_table -\set ON_ERROR_STOP 1 --- Size functions work anyway, similar to pg_table_size, et al. --- pg_table_size() can vary with platform so not outputting -SELECT 1 FROM pg_table_size('size_test_table'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('disttable'); - ?column? ----------- - 1 -(1 row) - -SELECT 1 FROM pg_table_size('nondisttable'); - ?column? ----------- - 1 -(1 row) - -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | 16384 | 24576 | 8192 | 49152 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 16384 | 24576 | 8192 | 49152 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 16384 | 0 | 24576 | data_node_1 -(3 rows) - -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------+-------------+-------------+-------------+-------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_3_chunk | 16384 | 24576 | 8192 | 49152 | - _timescaledb_internal | _hyper_1_4_chunk | 8192 | 16384 | 0 | 24576 | -(3 rows) - -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - 2 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - 1 | 1 | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 -(2 rows) - -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; - total_chunks | number_compressed_chunks | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ---------------+--------------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - 3 | 2 | 16384 | 32768 | 0 | 49152 | 32768 | 32768 | 16384 | 81920 | -(1 row) - -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+-----------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+------------- - _timescaledb_internal | _dist_hyper_2_2_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | data_node_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | Uncompressed | | | | | | | | | data_node_1 -(3 rows) - -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - chunk_schema | chunk_name | compression_status | before_compression_table_bytes | before_compression_index_bytes | before_compression_toast_bytes | before_compression_total_bytes | after_compression_table_bytes | after_compression_index_bytes | after_compression_toast_bytes | after_compression_total_bytes | node_name ------------------------+------------------+--------------------+--------------------------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+----------- - _timescaledb_internal | _hyper_1_1_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_3_chunk | Compressed | 8192 | 16384 | 0 | 24576 | 16384 | 16384 | 8192 | 40960 | - _timescaledb_internal | _hyper_1_4_chunk | Uncompressed | | | | | | | | | -(3 rows) - -SELECT * FROM hypertable_index_size('disttable_pkey'); - hypertable_index_size ------------------------ - 57344 -(1 row) - -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - hypertable_index_size ------------------------ - 40960 -(1 row) - -RESET ROLE; -GRANT SELECT ON disttable TO :ROLE_1; -GRANT SELECT ON nondisttable TO :ROLE_1; -SET ROLE :ROLE_1; --- Querying should now work -SELECT count(*) FROM disttable; - count -------- - 5 -(1 row) - --- hypertable_size should work now with SELECT privilege on tables -SELECT * FROM hypertable_size('disttable'); - hypertable_size ------------------ - 147456 -(1 row) - -SELECT * FROM hypertable_size('nondisttable'); - hypertable_size ------------------ - 131072 -(1 row) - -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+------------- - 24576 | 49152 | 8192 | 81920 | data_node_1 - 16384 | 32768 | 8192 | 57344 | data_node_2 - 0 | 8192 | 0 | 8192 | -(3 rows) - -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------- - 40960 | 73728 | 16384 | 131072 | -(1 row) - --- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser -\c :TEST_DBNAME :ROLE_1 -\unset ECHO -\set ON_ERROR_STOP 0 -SET timescaledb.ssl_dir TO 'ssldir'; -ERROR: parameter "timescaledb.ssl_dir" cannot be changed now -SET timescaledb.passfile TO 'passfile'; -ERROR: parameter "timescaledb.passfile" cannot be changed now -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -DROP DATABASE backend_1_1 WITH (FORCE); -DROP DATABASE backend_x_2 WITH (FORCE); -DROP DATABASE backend_2_1 WITH (FORCE); -DROP DATABASE frontend_1 WITH (FORCE); -DROP DATABASE frontend_2 WITH (FORCE); diff --git a/tsl/test/expected/dist_views-13.out b/tsl/test/expected/dist_views-13.out deleted file mode 100644 index 469b383c4f2..00000000000 --- a/tsl/test/expected/dist_views-13.out +++ /dev/null @@ -1,227 +0,0 @@ --- 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. ---------------------------------------------------- --- Test views and size_utils functions on distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_views_1 | db_dist_views_1 | t | t | t - db_dist_views_2 | db_dist_views_2 | t | t | t - db_dist_views_3 | db_dist_views_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET client_min_messages TO NOTICE; -SET ROLE :ROLE_1; -SELECT setseed(1); - setseed ---------- - -(1 row) - -CREATE TABLE dist_table(time timestamptz NOT NULL, device int, temp float, timedim date NOT NULL); -SELECT create_distributed_hypertable('dist_table', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,dist_table,t) -(1 row) - -SELECT add_dimension('dist_table', 'timedim', chunk_time_interval=>'7 days'::interval); - add_dimension ---------------------------------- - (3,public,dist_table,timedim,t) -(1 row) - -INSERT INTO dist_table SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 80, '2020-01-01' -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE dist_table SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Test views with compression -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('dist_table') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'dist_table'; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+---------------------------------------------------+------------- - public | dist_table | test_role_1 | 3 | 3 | t | t | 2 | {db_dist_views_1,db_dist_views_2,db_dist_views_3} | -(1 row) - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-----------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | t | | {db_dist_views_1,db_dist_views_2} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_2,db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_1,db_dist_views_3} -(3 rows) - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; - hypertable_schema | hypertable_name | dimension_number | column_name | column_type | dimension_type | time_interval | integer_interval | integer_now_func | num_partitions --------------------+-----------------+------------------+-------------+--------------------------+----------------+---------------+------------------+------------------+---------------- - public | dist_table | 1 | time | timestamp with time zone | Time | @ 7 days | | | - public | dist_table | 2 | device | integer | Space | | | | 3 - public | dist_table | 3 | timedim | date | Time | @ 7 days | | | -(3 rows) - -SELECT * FROM chunks_detailed_size('dist_table'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 8192 | 49152 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 8192 | 32768 | 8192 | 49152 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('dist_table'::regclass) -ORDER BY node_name;; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------- - 16384 | 81920 | 8192 | 106496 | db_dist_views_1 - 16384 | 81920 | 8192 | 106496 | db_dist_views_2 - 16384 | 81920 | 0 | 98304 | db_dist_views_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - ----tables with special characters in the name ---- -CREATE TABLE "quote'tab" ( a timestamp, b integer); -SELECT create_distributed_hypertable( '"quote''tab"', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_distributed_hypertable -------------------------------- - (2,public,quote'tab,t) -(1 row) - -INSERT into "quote'tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"quote''tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -CREATE TABLE "special#tab" ( a timestamp, b integer); -SELECT create_hypertable( 'special#tab', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_hypertable --------------------------- - (3,public,special#tab,t) -(1 row) - -INSERT into "special#tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"special#tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -SELECT * FROM hypertable_index_size( 'dist_table_time_idx') ; - hypertable_index_size ------------------------ - 114688 -(1 row) - --- Test chunk_replication_status view -SELECT * FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 4; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-----------------------------------+------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | 2 | 2 | {db_dist_views_2,db_dist_views_3} | {db_dist_views_1} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | 2 | 2 | {db_dist_views_3,db_dist_views_1} | {db_dist_views_2} - public | quote'tab | _timescaledb_internal | _dist_hyper_2_4_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} -(4 rows) - --- drop one chunk replica -SELECT _timescaledb_functions.chunk_drop_replica(format('%I.%I', chunk_schema, chunk_name)::regclass, replica_nodes[1]) -FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 1; - chunk_drop_replica --------------------- - -(1 row) - -SELECT * FROM timescaledb_experimental.chunk_replication_status -WHERE num_replicas < desired_num_replicas -ORDER BY chunk_schema, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 1 | {db_dist_views_2} | {db_dist_views_1,db_dist_views_3} -(1 row) - --- Example usage of finding data nodes to copy/move chunks between -SELECT - format('%I.%I', chunk_schema, chunk_name)::regclass AS chunk, - replica_nodes[1] AS copy_from_node, - non_replica_nodes[1] AS copy_to_node -FROM - timescaledb_experimental.chunk_replication_status -WHERE - num_replicas < desired_num_replicas -ORDER BY - chunk_schema, chunk_name; - chunk | copy_from_node | copy_to_node ----------------------------------------------+-----------------+----------------- - _timescaledb_internal._dist_hyper_1_1_chunk | db_dist_views_2 | db_dist_views_1 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_views-14.out b/tsl/test/expected/dist_views-14.out deleted file mode 100644 index 312a90b4e53..00000000000 --- a/tsl/test/expected/dist_views-14.out +++ /dev/null @@ -1,227 +0,0 @@ --- 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. ---------------------------------------------------- --- Test views and size_utils functions on distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_views_1 | db_dist_views_1 | t | t | t - db_dist_views_2 | db_dist_views_2 | t | t | t - db_dist_views_3 | db_dist_views_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET client_min_messages TO NOTICE; -SET ROLE :ROLE_1; -SELECT setseed(1); - setseed ---------- - -(1 row) - -CREATE TABLE dist_table(time timestamptz NOT NULL, device int, temp float, timedim date NOT NULL); -SELECT create_distributed_hypertable('dist_table', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,dist_table,t) -(1 row) - -SELECT add_dimension('dist_table', 'timedim', chunk_time_interval=>'7 days'::interval); - add_dimension ---------------------------------- - (3,public,dist_table,timedim,t) -(1 row) - -INSERT INTO dist_table SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 80, '2020-01-01' -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE dist_table SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Test views with compression -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('dist_table') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'dist_table'; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+---------------------------------------------------+------------- - public | dist_table | test_role_1 | 3 | 3 | t | t | 2 | {db_dist_views_1,db_dist_views_2,db_dist_views_3} | -(1 row) - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-----------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | t | | {db_dist_views_1,db_dist_views_2} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_2,db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_1,db_dist_views_3} -(3 rows) - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; - hypertable_schema | hypertable_name | dimension_number | column_name | column_type | dimension_type | time_interval | integer_interval | integer_now_func | num_partitions --------------------+-----------------+------------------+-------------+--------------------------+----------------+---------------+------------------+------------------+---------------- - public | dist_table | 1 | time | timestamp with time zone | Time | @ 7 days | | | - public | dist_table | 2 | device | integer | Space | | | | 3 - public | dist_table | 3 | timedim | date | Time | @ 7 days | | | -(3 rows) - -SELECT * FROM chunks_detailed_size('dist_table'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 16384 | 32768 | 8192 | 57344 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 16384 | 32768 | 8192 | 57344 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('dist_table'::regclass) -ORDER BY node_name;; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------- - 24576 | 81920 | 8192 | 114688 | db_dist_views_1 - 24576 | 81920 | 8192 | 114688 | db_dist_views_2 - 16384 | 81920 | 0 | 98304 | db_dist_views_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - ----tables with special characters in the name ---- -CREATE TABLE "quote'tab" ( a timestamp, b integer); -SELECT create_distributed_hypertable( '"quote''tab"', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_distributed_hypertable -------------------------------- - (2,public,quote'tab,t) -(1 row) - -INSERT into "quote'tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"quote''tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -CREATE TABLE "special#tab" ( a timestamp, b integer); -SELECT create_hypertable( 'special#tab', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_hypertable --------------------------- - (3,public,special#tab,t) -(1 row) - -INSERT into "special#tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"special#tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -SELECT * FROM hypertable_index_size( 'dist_table_time_idx') ; - hypertable_index_size ------------------------ - 114688 -(1 row) - --- Test chunk_replication_status view -SELECT * FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 4; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-----------------------------------+------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | 2 | 2 | {db_dist_views_2,db_dist_views_3} | {db_dist_views_1} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | 2 | 2 | {db_dist_views_3,db_dist_views_1} | {db_dist_views_2} - public | quote'tab | _timescaledb_internal | _dist_hyper_2_4_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} -(4 rows) - --- drop one chunk replica -SELECT _timescaledb_functions.chunk_drop_replica(format('%I.%I', chunk_schema, chunk_name)::regclass, replica_nodes[1]) -FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 1; - chunk_drop_replica --------------------- - -(1 row) - -SELECT * FROM timescaledb_experimental.chunk_replication_status -WHERE num_replicas < desired_num_replicas -ORDER BY chunk_schema, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 1 | {db_dist_views_2} | {db_dist_views_1,db_dist_views_3} -(1 row) - --- Example usage of finding data nodes to copy/move chunks between -SELECT - format('%I.%I', chunk_schema, chunk_name)::regclass AS chunk, - replica_nodes[1] AS copy_from_node, - non_replica_nodes[1] AS copy_to_node -FROM - timescaledb_experimental.chunk_replication_status -WHERE - num_replicas < desired_num_replicas -ORDER BY - chunk_schema, chunk_name; - chunk | copy_from_node | copy_to_node ----------------------------------------------+-----------------+----------------- - _timescaledb_internal._dist_hyper_1_1_chunk | db_dist_views_2 | db_dist_views_1 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/dist_views-15.out b/tsl/test/expected/dist_views-15.out deleted file mode 100644 index 312a90b4e53..00000000000 --- a/tsl/test/expected/dist_views-15.out +++ /dev/null @@ -1,227 +0,0 @@ --- 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. ---------------------------------------------------- --- Test views and size_utils functions on distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created ------------------+-----------------+--------------+------------------+------------------- - db_dist_views_1 | db_dist_views_1 | t | t | t - db_dist_views_2 | db_dist_views_2 | t | t | t - db_dist_views_3 | db_dist_views_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET client_min_messages TO NOTICE; -SET ROLE :ROLE_1; -SELECT setseed(1); - setseed ---------- - -(1 row) - -CREATE TABLE dist_table(time timestamptz NOT NULL, device int, temp float, timedim date NOT NULL); -SELECT create_distributed_hypertable('dist_table', 'time', 'device', replication_factor => 2); -WARNING: distributed hypertable is deprecated - create_distributed_hypertable -------------------------------- - (1,public,dist_table,t) -(1 row) - -SELECT add_dimension('dist_table', 'timedim', chunk_time_interval=>'7 days'::interval); - add_dimension ---------------------------------- - (3,public,dist_table,timedim,t) -(1 row) - -INSERT INTO dist_table SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 80, '2020-01-01' -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE dist_table SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); --- Test views with compression -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('dist_table') AS chunk -ORDER BY chunk -LIMIT 1; - compress_chunk ---------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk -(1 row) - -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'dist_table'; - hypertable_schema | hypertable_name | owner | num_dimensions | num_chunks | compression_enabled | is_distributed | replication_factor | data_nodes | tablespaces --------------------+-----------------+-------------+----------------+------------+---------------------+----------------+--------------------+---------------------------------------------------+------------- - public | dist_table | test_role_1 | 3 | 3 | t | t | 2 | {db_dist_views_1,db_dist_views_2,db_dist_views_3} | -(1 row) - -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | primary_dimension | primary_dimension_type | range_start | range_end | range_start_integer | range_end_integer | is_compressed | chunk_tablespace | data_nodes --------------------+-----------------+-----------------------+-----------------------+-------------------+--------------------------+------------------------------+------------------------------+---------------------+-------------------+---------------+------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | t | | {db_dist_views_1,db_dist_views_2} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_2,db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | time | timestamp with time zone | Wed Feb 28 16:00:00 2018 PST | Wed Mar 07 16:00:00 2018 PST | | | f | | {db_dist_views_1,db_dist_views_3} -(3 rows) - -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; - hypertable_schema | hypertable_name | dimension_number | column_name | column_type | dimension_type | time_interval | integer_interval | integer_now_func | num_partitions --------------------+-----------------+------------------+-------------+--------------------------+----------------+---------------+------------------+------------------+---------------- - public | dist_table | 1 | time | timestamp with time zone | Time | @ 7 days | | | - public | dist_table | 2 | device | integer | Space | | | | 3 - public | dist_table | 3 | timedim | date | Time | @ 7 days | | | -(3 rows) - -SELECT * FROM chunks_detailed_size('dist_table'::regclass) -ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_1_1_chunk | 16384 | 32768 | 8192 | 57344 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_1_chunk | 16384 | 32768 | 8192 | 57344 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_1_2_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_1_3_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_3 -(6 rows) - -SELECT * FROM hypertable_detailed_size('dist_table'::regclass) -ORDER BY node_name;; - table_bytes | index_bytes | toast_bytes | total_bytes | node_name --------------+-------------+-------------+-------------+----------------- - 24576 | 81920 | 8192 | 114688 | db_dist_views_1 - 24576 | 81920 | 8192 | 114688 | db_dist_views_2 - 16384 | 81920 | 0 | 98304 | db_dist_views_3 - 0 | 16384 | 0 | 16384 | -(4 rows) - ----tables with special characters in the name ---- -CREATE TABLE "quote'tab" ( a timestamp, b integer); -SELECT create_distributed_hypertable( '"quote''tab"', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: distributed hypertable is deprecated -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_distributed_hypertable -------------------------------- - (2,public,quote'tab,t) -(1 row) - -INSERT into "quote'tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"quote''tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+-----------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_4_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_5_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_6_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_2_7_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -CREATE TABLE "special#tab" ( a timestamp, b integer); -SELECT create_hypertable( 'special#tab', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -WARNING: column type "timestamp without time zone" used for "a" does not follow best practices -NOTICE: adding not-null constraint to column "a" - create_hypertable --------------------------- - (3,public,special#tab,t) -(1 row) - -INSERT into "special#tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"special#tab"') ORDER BY chunk_name, node_name; - chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name ------------------------+------------------------+-------------+-------------+-------------+-------------+----------------- - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_10_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_11_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_8_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_1 - _timescaledb_internal | _dist_hyper_3_9_chunk | 8192 | 32768 | 0 | 40960 | db_dist_views_2 -(8 rows) - -SELECT * FROM hypertable_index_size( 'dist_table_time_idx') ; - hypertable_index_size ------------------------ - 114688 -(1 row) - --- Test chunk_replication_status view -SELECT * FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 4; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-----------------------------------+------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} - public | dist_table | _timescaledb_internal | _dist_hyper_1_2_chunk | 2 | 2 | {db_dist_views_2,db_dist_views_3} | {db_dist_views_1} - public | dist_table | _timescaledb_internal | _dist_hyper_1_3_chunk | 2 | 2 | {db_dist_views_3,db_dist_views_1} | {db_dist_views_2} - public | quote'tab | _timescaledb_internal | _dist_hyper_2_4_chunk | 2 | 2 | {db_dist_views_1,db_dist_views_2} | {db_dist_views_3} -(4 rows) - --- drop one chunk replica -SELECT _timescaledb_functions.chunk_drop_replica(format('%I.%I', chunk_schema, chunk_name)::regclass, replica_nodes[1]) -FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 1; - chunk_drop_replica --------------------- - -(1 row) - -SELECT * FROM timescaledb_experimental.chunk_replication_status -WHERE num_replicas < desired_num_replicas -ORDER BY chunk_schema, chunk_name; - hypertable_schema | hypertable_name | chunk_schema | chunk_name | desired_num_replicas | num_replicas | replica_nodes | non_replica_nodes --------------------+-----------------+-----------------------+-----------------------+----------------------+--------------+-------------------+----------------------------------- - public | dist_table | _timescaledb_internal | _dist_hyper_1_1_chunk | 2 | 1 | {db_dist_views_2} | {db_dist_views_1,db_dist_views_3} -(1 row) - --- Example usage of finding data nodes to copy/move chunks between -SELECT - format('%I.%I', chunk_schema, chunk_name)::regclass AS chunk, - replica_nodes[1] AS copy_from_node, - non_replica_nodes[1] AS copy_to_node -FROM - timescaledb_experimental.chunk_replication_status -WHERE - num_replicas < desired_num_replicas -ORDER BY - chunk_schema, chunk_name; - chunk | copy_from_node | copy_to_node ----------------------------------------------+-----------------+----------------- - _timescaledb_internal._dist_hyper_1_1_chunk | db_dist_views_2 | db_dist_views_1 -(1 row) - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/remote_connection.out b/tsl/test/expected/remote_connection.out deleted file mode 100644 index cadc8d86426..00000000000 --- a/tsl/test/expected/remote_connection.out +++ /dev/null @@ -1,80 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER -CREATE FUNCTION test.remote_connection_tests() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_connection' -LANGUAGE C STRICT; -CREATE FUNCTION test.remote_async_tests() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_async' -LANGUAGE C STRICT; -CREATE FUNCTION test.send_remote_query_that_generates_exception() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_bad_remote_query' -LANGUAGE C STRICT; -CREATE FUNCTION test.get_connection_stats() -RETURNS TABLE(connections_created bigint, connections_closed bigint, results_created bigint, results_cleared bigint) -AS :TSL_MODULE_PATHNAME, 'ts_test_get_connection_stats' -LANGUAGE C STRICT; --- =================================================================== --- create tables --- =================================================================== -CREATE SCHEMA "S 1"; -CREATE TABLE "S 1"."T 1" ( - "C 1" int NOT NULL, - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10), - CONSTRAINT t1_pkey PRIMARY KEY ("C 1") -); -ANALYZE "S 1"."T 1"; -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10 - FROM generate_series(1, 1000) id; --- =================================================================== --- run tests --- =================================================================== -\set VERBOSITY verbose -SELECT * FROM test.get_connection_stats(); - connections_created | connections_closed | results_created | results_cleared ----------------------+--------------------+-----------------+----------------- - 0 | 0 | 0 | 0 -(1 row) - -\set ON_ERROR_STOP 0 -SELECT test.send_remote_query_that_generates_exception(); -ERROR: XX000: bad query error thrown from test -LOCATION: ts_test_bad_remote_query, connection.c:222 -\set ON_ERROR_STOP 1 -SELECT * FROM test.get_connection_stats(); - connections_created | connections_closed | results_created | results_cleared ----------------------+--------------------+-----------------+----------------- - 1 | 1 | 9 | 9 -(1 row) - -SELECT test.remote_connection_tests(); - remote_connection_tests -------------------------- - -(1 row) - -SET client_min_messages TO ERROR; -SELECT test.remote_async_tests(); - remote_async_tests --------------------- - -(1 row) - -\echo 'End Of Test' -End Of Test diff --git a/tsl/test/expected/remote_connection_cache.out b/tsl/test/expected/remote_connection_cache.out deleted file mode 100644 index d0d399d3a2f..00000000000 --- a/tsl/test/expected/remote_connection_cache.out +++ /dev/null @@ -1,85 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -CREATE FUNCTION _timescaledb_internal.test_remote_connection_cache() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_connection_cache' -LANGUAGE C STRICT; -CREATE FUNCTION _timescaledb_internal.test_alter_data_node(node_name NAME) -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_alter_data_node' -LANGUAGE C STRICT; -SET client_min_messages TO WARNING; -SELECT node_name, database, node_created, extension_created -FROM add_data_node('loopback_1', host => 'localhost', database => :'DN_DBNAME_1', - port => current_setting('port')::int); -WARNING: adding data node is deprecated - node_name | database | node_created | extension_created -------------+------------------------------+--------------+------------------- - loopback_1 | db_remote_connection_cache_1 | t | t -(1 row) - -SELECT node_name, database, node_created, extension_created -FROM add_data_node('loopback_2', host => 'localhost', database => :'DN_DBNAME_2', - port => current_setting('port')::int); -WARNING: adding data node is deprecated - node_name | database | node_created | extension_created -------------+------------------------------+--------------+------------------- - loopback_2 | db_remote_connection_cache_2 | t | t -(1 row) - -SET client_min_messages TO INFO; -SELECT _timescaledb_internal.test_remote_connection_cache(); - test_remote_connection_cache ------------------------------- - -(1 row) - --- Test that connection cache entries for a role gets invalidated when --- we rename the role -GRANT USAGE ON FOREIGN SERVER loopback_1, loopback_2 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE testtable (time timestamptz, location int, temp float); -SELECT * FROM create_distributed_hypertable('testtable', 'time', 'location'); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "time" - hypertable_id | schema_name | table_name | created ----------------+-------------+------------+--------- - 1 | public | testtable | t -(1 row) - -INSERT INTO testtable VALUES ('2021-09-19', 1, 13.2); --- Should show valid connections for ROLE_1 -SELECT node_name, user_name, invalidated -FROM _timescaledb_functions.show_connection_cache() -WHERE user_name=:'ROLE_1' -ORDER BY 1,2; - node_name | user_name | invalidated -------------+-------------+------------- - loopback_1 | test_role_1 | f - loopback_2 | test_role_1 | f -(2 rows) - -RESET ROLE; -BEGIN; --- Renaming the role should invalidate the connection cache entries --- for ROLE_1/bob. The connections will be recreated on next cache --- fetch. -ALTER ROLE :ROLE_1 RENAME TO bob; -SELECT node_name, user_name, invalidated -FROM _timescaledb_functions.show_connection_cache() -WHERE user_name='bob' -ORDER BY 1,2; - node_name | user_name | invalidated -------------+-----------+------------- - loopback_1 | bob | t - loopback_2 | bob | t -(2 rows) - -ROLLBACK; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); diff --git a/tsl/test/expected/remote_copy.out b/tsl/test/expected/remote_copy.out deleted file mode 100644 index f0d1105b58a..00000000000 --- a/tsl/test/expected/remote_copy.out +++ /dev/null @@ -1,503 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated -WARNING: adding data node is deprecated - node_name | database | node_created | database_created | extension_created -------------------+------------------+--------------+------------------+------------------- - db_remote_copy_1 | db_remote_copy_1 | t | t | t - db_remote_copy_2 | db_remote_copy_2 | t | t | t - db_remote_copy_3 | db_remote_copy_3 | t | t | t -(3 rows) - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET timescaledb.hide_data_node_name_in_errors = 'on'; --- Start out testing text copy code -SET timescaledb.enable_connection_binary_data=false; -SET ROLE :ROLE_1; --- Use some horrible names to make sure the parsing code works -CREATE TABLE "+ri(k33_')" ( - "thyme" bigint NOT NULL, - "))_" double precision NOT NULL, - "flavor" text DEFAULT 'mint', - "pH" float DEFAULT 7.0, - optional text -); -SELECT create_hypertable('"+ri(k33_'')"', 'thyme', partitioning_column=>'pH', number_partitions=>4, chunk_time_interval => 100, replication_factor => 2); - create_hypertable ---------------------------- - (1,public,"+ri(k33_')",t) -(1 row) - --- Use local table as an etalon -create table copy_local(like "+ri(k33_')"); -COPY copy_local FROM STDIN; -\copy copy_local("pH", "))_", thyme) fROm stdIN deLIMitER '-'; -cOpy copy_local(thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -COPY copy_local FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -select * from copy_local order by 1; - thyme | ))_ | flavor | pH | optional ---------+----------------------+------------------------+------+---------- - 1 | 11 | strawberry | 2.3 | stuff - 15 | 403 | | 1 | - 203 | 3.21321 | something like lemon | 1 | - 208 | 40 | | 0.01 | - 315 | 37 | | 10 | - 333 | 2309424231 | _''garbled*(#\)@#$*) | 1 | - 342 | 4324 | "empties" | 4 | \N - 4201 | 3.33333333333333e+27 | "" | 1 | empties - 120321 | 4.43244243242544 | | 0 | -(9 rows) - --- Run some successful copies -COPY "+ri(k33_')" FROM STDIN; -\copy public . "+ri(k33_')" ("pH", "))_" , thyme) fROm stdIN deLIMitER '-'; -cOpy public."+ri(k33_')" (thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -COPY "+ri(k33_')" FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FREEZE, FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -select * from copy_local order by 1; - thyme | ))_ | flavor | pH | optional ---------+----------------------+------------------------+------+---------- - 1 | 11 | strawberry | 2.3 | stuff - 15 | 403 | | 1 | - 203 | 3.21321 | something like lemon | 1 | - 208 | 40 | | 0.01 | - 315 | 37 | | 10 | - 333 | 2309424231 | _''garbled*(#\)@#$*) | 1 | - 342 | 4324 | "empties" | 4 | \N - 4201 | 3.33333333333333e+27 | "" | 1 | empties - 120321 | 4.43244243242544 | | 0 | -(9 rows) - --- Run some error cases -\set ON_ERROR_STOP 0 --- Bad input -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -ERROR: invalid input syntax for type double precision: "grey" --- Missing paritioning column -COPY "+ri(k33_')" (thYme, "))_", "flavor") FROM STDIN; -ERROR: unable to use default value for partitioning column "pH" --- Missing required column, these generate a WARNING with a transaction id in them (too flimsy to output) -SET client_min_messages TO ERROR; -COPY "+ri(k33_')" (thyme, flavor, "pH") FROM STDIN WITH DELIMITER ','; -ERROR: []: null value in column "))_" of relation "_dist_hyper_1_1_chunk" violates not-null constraint -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -ERROR: []: null value in column "))_" of relation "_dist_hyper_1_4_chunk" violates not-null constraint -SET client_min_messages TO INFO; --- Invalid data after new chunk creation, data and chunks should be rolled back -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -ERROR: invalid input syntax for type double precision: "ten" -\set ON_ERROR_STOP 1 --- Now do some testing of the binary frontend/backend path. -SET timescaledb.enable_connection_binary_data=true; -COPY "+ri(k33_')" FROM STDIN; -\copy public . "+ri(k33_')" ("pH", "))_" , thyme) fROm stdIN deLIMitER '-'; -cOpy public."+ri(k33_')" (thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -COPY "+ri(k33_')" FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FREEZE, FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -SELECT * FROM "+ri(k33_')" ORDER BY 1; - thyme | ))_ | flavor | pH | optional ----------+----------------------+------------------------+-------+---------- - 1 | 11 | strawberry | 2.3 | stuff - 10 | 11 | strawberry | 12.3 | stuff - 15 | 403 | | 1 | - 150 | 403 | | 10 | - 203 | 3.21321 | something like lemon | 1 | - 208 | 40 | mint | 0.01 | - 315 | 37 | mint | 10 | - 333 | 2309424231 | _''garbled*(#\)@#$*) | 1 | - 342 | 4324 | "empties" | 4 | \N - 2030 | 3.21321 | something like lemon | 10 | - 2080 | 40 | mint | 0.001 | - 3150 | 37 | mint | 100 | - 3330 | 2309424231 | _''garbled*(#\)@#$*) | 10 | - 3420 | 4324 | "empties" | 40 | \N - 4201 | 3.33333333333333e+27 | "" | 1 | empties - 42010 | 3.33333333333333e+27 | "" | 1 | empties - 120321 | 4.43244243242544 | | 0 | - 1203210 | 4.43244243242544 | | 0 | -(18 rows) - -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY 1; - id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk -----+---------------+-----------------------+------------------------+---------------------+---------+--------+----------- - 1 | 1 | _timescaledb_internal | _dist_hyper_1_1_chunk | | f | 0 | f - 2 | 1 | _timescaledb_internal | _dist_hyper_1_2_chunk | | f | 0 | f - 3 | 1 | _timescaledb_internal | _dist_hyper_1_3_chunk | | f | 0 | f - 4 | 1 | _timescaledb_internal | _dist_hyper_1_4_chunk | | f | 0 | f - 5 | 1 | _timescaledb_internal | _dist_hyper_1_5_chunk | | f | 0 | f - 6 | 1 | _timescaledb_internal | _dist_hyper_1_6_chunk | | f | 0 | f - 7 | 1 | _timescaledb_internal | _dist_hyper_1_7_chunk | | f | 0 | f - 8 | 1 | _timescaledb_internal | _dist_hyper_1_8_chunk | | f | 0 | f - 12 | 1 | _timescaledb_internal | _dist_hyper_1_12_chunk | | f | 0 | f - 13 | 1 | _timescaledb_internal | _dist_hyper_1_13_chunk | | f | 0 | f - 14 | 1 | _timescaledb_internal | _dist_hyper_1_14_chunk | | f | 0 | f - 15 | 1 | _timescaledb_internal | _dist_hyper_1_15_chunk | | f | 0 | f - 16 | 1 | _timescaledb_internal | _dist_hyper_1_16_chunk | | f | 0 | f - 17 | 1 | _timescaledb_internal | _dist_hyper_1_17_chunk | | f | 0 | f - 18 | 1 | _timescaledb_internal | _dist_hyper_1_18_chunk | | f | 0 | f - 19 | 1 | _timescaledb_internal | _dist_hyper_1_19_chunk | | f | 0 | f -(16 rows) - -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1, 3; - chunk_id | node_chunk_id | node_name -----------+---------------+------------------ - 1 | 1 | db_remote_copy_1 - 1 | 1 | db_remote_copy_3 - 2 | 2 | db_remote_copy_1 - 2 | 2 | db_remote_copy_3 - 3 | 3 | db_remote_copy_1 - 3 | 1 | db_remote_copy_2 - 4 | 4 | db_remote_copy_1 - 4 | 2 | db_remote_copy_2 - 5 | 5 | db_remote_copy_1 - 5 | 3 | db_remote_copy_2 - 6 | 6 | db_remote_copy_1 - 6 | 4 | db_remote_copy_2 - 7 | 7 | db_remote_copy_1 - 7 | 5 | db_remote_copy_2 - 8 | 8 | db_remote_copy_1 - 8 | 6 | db_remote_copy_2 - 12 | 11 | db_remote_copy_1 - 12 | 8 | db_remote_copy_2 - 13 | 12 | db_remote_copy_1 - 13 | 9 | db_remote_copy_2 - 14 | 13 | db_remote_copy_1 - 14 | 10 | db_remote_copy_2 - 15 | 14 | db_remote_copy_1 - 15 | 11 | db_remote_copy_2 - 16 | 15 | db_remote_copy_1 - 16 | 12 | db_remote_copy_2 - 17 | 16 | db_remote_copy_1 - 17 | 13 | db_remote_copy_2 - 18 | 17 | db_remote_copy_1 - 18 | 14 | db_remote_copy_2 - 19 | 18 | db_remote_copy_1 - 19 | 6 | db_remote_copy_3 -(32 rows) - -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 3; - hypertable_id | node_hypertable_id | node_name | block_chunks ----------------+--------------------+------------------+-------------- - 1 | 1 | db_remote_copy_1 | f - 1 | 1 | db_remote_copy_2 | f - 1 | 1 | db_remote_copy_3 | f -(3 rows) - -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk - _timescaledb_internal._dist_hyper_1_6_chunk - _timescaledb_internal._dist_hyper_1_7_chunk - _timescaledb_internal._dist_hyper_1_8_chunk - _timescaledb_internal._dist_hyper_1_12_chunk - _timescaledb_internal._dist_hyper_1_13_chunk - _timescaledb_internal._dist_hyper_1_14_chunk - _timescaledb_internal._dist_hyper_1_15_chunk - _timescaledb_internal._dist_hyper_1_16_chunk - _timescaledb_internal._dist_hyper_1_17_chunk - _timescaledb_internal._dist_hyper_1_18_chunk - _timescaledb_internal._dist_hyper_1_19_chunk -(16 rows) - -\c :DATA_NODE_1 -SELECT * FROM "+ri(k33_')" ORDER BY 1; - thyme | ))_ | flavor | pH | optional ----------+----------------------+------------------------+-------+---------- - 1 | 11 | strawberry | 2.3 | stuff - 10 | 11 | strawberry | 12.3 | stuff - 15 | 403 | | 1 | - 150 | 403 | | 10 | - 203 | 3.21321 | something like lemon | 1 | - 208 | 40 | mint | 0.01 | - 315 | 37 | mint | 10 | - 333 | 2309424231 | _''garbled*(#\)@#$*) | 1 | - 342 | 4324 | "empties" | 4 | \N - 2030 | 3.21321 | something like lemon | 10 | - 2080 | 40 | mint | 0.001 | - 3150 | 37 | mint | 100 | - 3330 | 2309424231 | _''garbled*(#\)@#$*) | 10 | - 3420 | 4324 | "empties" | 40 | \N - 4201 | 3.33333333333333e+27 | "" | 1 | empties - 42010 | 3.33333333333333e+27 | "" | 1 | empties - 120321 | 4.43244243242544 | | 0 | - 1203210 | 4.43244243242544 | | 0 | -(18 rows) - -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk - _timescaledb_internal._dist_hyper_1_6_chunk - _timescaledb_internal._dist_hyper_1_7_chunk - _timescaledb_internal._dist_hyper_1_8_chunk - _timescaledb_internal._dist_hyper_1_12_chunk - _timescaledb_internal._dist_hyper_1_13_chunk - _timescaledb_internal._dist_hyper_1_14_chunk - _timescaledb_internal._dist_hyper_1_15_chunk - _timescaledb_internal._dist_hyper_1_16_chunk - _timescaledb_internal._dist_hyper_1_17_chunk - _timescaledb_internal._dist_hyper_1_18_chunk - _timescaledb_internal._dist_hyper_1_19_chunk -(16 rows) - -\c :DATA_NODE_2 -SELECT * FROM "+ri(k33_')" ORDER BY 1; - thyme | ))_ | flavor | pH | optional ----------+----------------------+------------------------+-------+---------- - 10 | 11 | strawberry | 12.3 | stuff - 15 | 403 | | 1 | - 150 | 403 | | 10 | - 203 | 3.21321 | something like lemon | 1 | - 315 | 37 | mint | 10 | - 333 | 2309424231 | _''garbled*(#\)@#$*) | 1 | - 342 | 4324 | "empties" | 4 | \N - 2030 | 3.21321 | something like lemon | 10 | - 2080 | 40 | mint | 0.001 | - 3150 | 37 | mint | 100 | - 3330 | 2309424231 | _''garbled*(#\)@#$*) | 10 | - 4201 | 3.33333333333333e+27 | "" | 1 | empties - 42010 | 3.33333333333333e+27 | "" | 1 | empties - 120321 | 4.43244243242544 | | 0 | - 1203210 | 4.43244243242544 | | 0 | -(15 rows) - -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_3_chunk - _timescaledb_internal._dist_hyper_1_4_chunk - _timescaledb_internal._dist_hyper_1_5_chunk - _timescaledb_internal._dist_hyper_1_6_chunk - _timescaledb_internal._dist_hyper_1_7_chunk - _timescaledb_internal._dist_hyper_1_8_chunk - _timescaledb_internal._dist_hyper_1_12_chunk - _timescaledb_internal._dist_hyper_1_13_chunk - _timescaledb_internal._dist_hyper_1_14_chunk - _timescaledb_internal._dist_hyper_1_15_chunk - _timescaledb_internal._dist_hyper_1_16_chunk - _timescaledb_internal._dist_hyper_1_17_chunk - _timescaledb_internal._dist_hyper_1_18_chunk -(13 rows) - -\c :DATA_NODE_3 -SELECT * FROM "+ri(k33_')" ORDER BY 1; - thyme | ))_ | flavor | pH | optional --------+------+------------+------+---------- - 1 | 11 | strawberry | 2.3 | stuff - 208 | 40 | mint | 0.01 | - 3420 | 4324 | "empties" | 40 | \N -(3 rows) - -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; - show_chunks ----------------------------------------------- - _timescaledb_internal._dist_hyper_1_1_chunk - _timescaledb_internal._dist_hyper_1_2_chunk - _timescaledb_internal._dist_hyper_1_19_chunk -(3 rows) - -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; -DROP TABLE "+ri(k33_')" CASCADE; --- Some more test for escaping and quoting -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'text'; -create table escapes(t int, value text); -select create_distributed_hypertable('escapes', 't', 'value', chunk_time_interval => 100); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "t" - create_distributed_hypertable -------------------------------- - (2,public,escapes,t) -(1 row) - -\copy escapes from stdin -\copy (select * from escapes order by escapes) to stdout -1 \t\b\f\n\r\t\v\\ -2 \t -3 a\nb -4 ddddd -5 \\ -7 \\N -9 end -10 "'"'" -11 '"'"' -12 ' --- Null values not allowed for partitioning columns -\set ON_ERROR_STOP off -\copy escapes from stdin -ERROR: NULL value in column "value" violates not-null constraint -\copy escapes from program 'printf "8\n\\.\n"' -ERROR: the number of columns doesn't match -\copy escapes from program 'printf "8\t\n\\.\n"' -\copy (select * from escapes order by escapes) to stdout -1 \t\b\f\n\r\t\v\\ -2 \t -3 a\nb -4 ddddd -5 \\ -7 \\N -8 -9 end -10 "'"'" -11 '"'"' -12 ' -\set ON_ERROR_STOP on --- Test null values. -create table null_values(t int, value text); -select create_distributed_hypertable('null_values', 't', chunk_time_interval => 100); -WARNING: distributed hypertable is deprecated -NOTICE: adding not-null constraint to column "t" - create_distributed_hypertable -------------------------------- - (3,public,null_values,t) -(1 row) - -\copy null_values from program 'printf "6\t\\N\n8\t\n\\.\n"' -\copy (select * from null_values order by null_values) to stdout -6 \N -8 --- CSV -\copy (select * from escapes order by escapes) to stdout with (format csv); -1,"  - \" -2, -3,"a -b" -4,ddddd -5,\ -7,\N -8,"" -9,end -10,"""'""'""" -11,"'""'""'" -12,' -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.tsv'; -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.csv' with (format csv); -truncate escapes; -\copy escapes from 'remote-copy-escapes.csv' with (format csv); -\copy (select * from escapes order by escapes) to stdout; -1 \t\b\f\n\r\t\v\\ -2 \t -3 a\nb -4 ddddd -5 \\ -7 \\N -8 -9 end -10 "'"'" -11 '"'"' -12 ' --- Check the result with diff -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-escapes.tsv -'; --- Different delimiter -\copy (select * from escapes order by escapes) to stdout with (format csv, delimiter '"', quote ''''); -1"'  - \' -2" -3"'a -b' -4"ddddd -5"\ -7"\N -8"'' -9"end -10"'"''"''"' -11"'''"''"''' -12"'''' -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.csv' with (format csv, delimiter '"', quote '''', null ','); -truncate escapes; -\copy escapes from 'remote-copy-escapes.csv' with (format csv, delimiter '"', quote '''', null ','); -\copy (select * from escapes order by escapes) to stdout; -1 \t\b\f\n\r\t\v\\ -2 \t -3 a\nb -4 ddddd -5 \\ -7 \\N -8 -9 end -10 "'"'" -11 '"'"' -12 ' --- Check the result with diff -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-escapes.tsv -'; --- Longer values -truncate table escapes; -\copy escapes from stdin -\copy escapes from stdin -select sum(t), sum(length(value)) from escapes; - sum | sum ------+------ - 276 | 9214 -(1 row) - --- Check different file encoding -truncate table escapes; -\copy escapes from stdin -\copy (select * from escapes order by escapes) to 'remote-copy-sjis.tsv' with (encoding 'SJIS'); -\copy (select * from escapes order by escapes) to 'remote-copy-utf8.tsv' with (encoding 'UTF8'); --- Check that output encoding works at all, and the UTF8 and SJIS files are --- different. If you set SQL_ASCII as the server encoding, it just silently --- ignores the encoding options. -\set ON_ERROR_STOP 0 -\copy (select * from escapes order by escapes) to program 'diff -q -- remote-copy-utf8.tsv -' with (encoding 'SJIS'); -Files remote-copy-utf8.tsv and - differ -diff -q -- remote-copy-utf8.tsv -: child process exited with exit code 1 -\set ON_ERROR_STOP 1 -truncate escapes; -\copy escapes from 'remote-copy-sjis.tsv' with (encoding 'SJIS'); -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-utf8.tsv -' with (encoding 'UTF8'); -drop table null_values; -drop table escapes; -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_1'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node(:'DATA_NODE_2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT * FROM delete_data_node(:'DATA_NODE_3'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/expected/remote_stmt_params.out b/tsl/test/expected/remote_stmt_params.out deleted file mode 100644 index 1aea04eba63..00000000000 --- a/tsl/test/expected/remote_stmt_params.out +++ /dev/null @@ -1,22 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER -CREATE OR REPLACE FUNCTION _timescaledb_internal.test_stmt_params_format(binary BOOL) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_stmt_params_format' -LANGUAGE C STRICT; --- by default we use binary format -SELECT _timescaledb_internal.test_stmt_params_format(true); - test_stmt_params_format -------------------------- - -(1 row) - -SET timescaledb.enable_connection_binary_data = false; -SELECT _timescaledb_internal.test_stmt_params_format(false); - test_stmt_params_format -------------------------- - -(1 row) - diff --git a/tsl/test/expected/remote_txn.out b/tsl/test/expected/remote_txn.out deleted file mode 100644 index e8985fed13c..00000000000 --- a/tsl/test/expected/remote_txn.out +++ /dev/null @@ -1,1316 +0,0 @@ --- 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. --- =================================================================== --- create FDW objects --- =================================================================== -\c :TEST_DBNAME :ROLE_SUPERUSER -\ir include/remote_exec.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. -CREATE SCHEMA IF NOT EXISTS test; -psql:include/remote_exec.sql:5: NOTICE: schema "test" already exists, skipping -GRANT USAGE ON SCHEMA test TO PUBLIC; -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; -CREATE OR REPLACE FUNCTION remote_node_killer_set_event(text, text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_node_killer_set_event' -LANGUAGE C; -CREATE OR REPLACE FUNCTION test_remote_txn_persistent_record(srv_name name) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_persistent_record' -LANGUAGE C; --- To ensure predictability, we want to kill the remote backend when it's in --- the midst of processing the transaction. To ensure that the access node --- sets the event handler and then takes an exclusive session lock on the --- "remote_conn_xact_end" advisory lock via "debug_waitpoint_enable" function --- --- The "RegisterXactCallback" callback on the remote backend tries to take --- this same advisory lock in shared mode and waits. This allows the event --- handler enough time to kill this remote backend at the right time --- --- Don't forget to release lock via debug_waitpoint_release on the access node --- since it's a session level advisory lock --- -CREATE OR REPLACE FUNCTION add_loopback_server( - server_name NAME, - host TEXT = 'localhost', - database NAME = current_database(), - port INTEGER = inet_server_port(), - if_not_exists BOOLEAN = FALSE, - bootstrap BOOLEAN = TRUE, - password TEXT = NULL -) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME, - server_created BOOL, database_created BOOL, extension_created BOOL) -AS :TSL_MODULE_PATHNAME, 'ts_unchecked_add_data_node' -LANGUAGE C; -SELECT server_name, database, server_created, database_created, extension_created FROM add_loopback_server('loopback', database => :'TEST_DBNAME', bootstrap => false); -WARNING: adding data node is deprecated - server_name | database | server_created | database_created | extension_created --------------+---------------+----------------+------------------+------------------- - loopback | db_remote_txn | t | f | f -(1 row) - -SELECT server_name, database, server_created, database_created, extension_created FROM add_loopback_server('loopback2', database => :'TEST_DBNAME', bootstrap => false); -WARNING: adding data node is deprecated - server_name | database | server_created | database_created | extension_created --------------+---------------+----------------+------------------+------------------- - loopback2 | db_remote_txn | t | f | f -(1 row) - --- =================================================================== --- create objects used through FDW loopback server --- =================================================================== -CREATE SCHEMA "S 1"; -CREATE TABLE "S 1"."T 1" ( - "C 1" int NOT NULL, - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10), - CONSTRAINT t1_pkey PRIMARY KEY ("C 1") -); -ANALYZE "S 1"."T 1"; -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10 - FROM generate_series(1, 1000) id; -\set ON_ERROR_STOP 0 -SELECT test_remote_txn_persistent_record('loopback'); - test_remote_txn_persistent_record ------------------------------------ - -(1 row) - --- =================================================================== --- 1 pc tests --- =================================================================== ---successfull transaction -SET timescaledb.enable_2pc = false; ---initially, there are no connections in the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - --expect to see one connection in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -COMMIT; ---connection should remain, idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20001; - count -------- - 1 -(1 row) - ---aborted transaction -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (20002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - --existing connection, in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -ROLLBACK; ---connection should remain, in idle state after rollback -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20002; - count -------- - 0 -(1 row) - ---constraint violation -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" -COMMIT; --- Connection should remain after conflict, in idle state -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - ---the next few statements inject faults before the commit. They should all fail ---and be rolled back with no unresolved state --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('pre-commit', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20003,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - -COMMIT; -ERROR: [loopback]: terminating connection due to administrator command -RESET client_min_messages; -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - --- Failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20003; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('waiting-commit', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20004,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -COMMIT; -ERROR: [loopback]: terminating connection due to administrator command -RESET client_min_messages; -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - ---connection failed during commit, so should be cleared from the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - ---during waiting-commit the data node process could die before or after ---executing the commit on the remote node. So the behaviour here is non-deterministic ---this is the bad part of 1-pc transactions. ---there are no prepared txns in either case -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---fail the connection before the abort -BEGIN; - SELECT remote_node_killer_set_event('pre-abort', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (20005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - --- since the error messages/warnings from this ROLLBACK varies between --- platforms/environments we remove it from test output and show --- SQLSTATE instead. SQLSTATE should be 00000 since we are not --- throwing errors during rollback/abort and it should succeed in any --- case. -\echo 'ROLLBACK SQLSTATE' :SQLSTATE -ROLLBACK SQLSTATE 00000 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20005; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---the failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - ---block preparing transactions on the access node -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (20006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - -PREPARE TRANSACTION 'test-2'; -ERROR: cannot prepare a transaction that modified remote tables --- =================================================================== --- 2 pc tests --- =================================================================== ---undo changes from 1-pc tests -DELETE FROM "S 1"."T 1" where "C 1" >= 20000; -SET timescaledb.enable_2pc = true; -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - ---simple commit -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -COMMIT; ---connection should remain in idle state -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10001; - count -------- - 1 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---simple -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (11001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (11001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -ROLLBACK; ---rolled back transaction, but connection should remain in idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 11001; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---constraint violation should fail the txn -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" -COMMIT; ---connection should remain in idle after constraint violation -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - ---the next few statements inject faults before the commit. They should all fail ---and be rolled back with no unresolved state -BEGIN; - SELECT remote_node_killer_set_event('pre-prepare-transaction', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 08006 connection_failure -\echo 'COMMIT SQLSTATE' :SQLSTATE -COMMIT SQLSTATE 08006 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - ---the connection was killed, so should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10002; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -BEGIN; - SELECT remote_node_killer_set_event('waiting-prepare-transaction', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10003,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10003,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 08006 connection_failure -\echo 'COMMIT SQLSTATE' :SQLSTATE -COMMIT SQLSTATE 08006 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - ---the connection should be cleared from the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10003; - count -------- - 0 -(1 row) - ---during waiting-prepare-transaction the data node process could die before or after ---executing the prepare transaction. To be safe to either case rollback using heal_server. -SELECT count(*) FROM _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - count -------- - 1 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -SELECT count(*) from _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - ---the following only breaks stuff in post-commit so commit should succeed ---but leave transaction in an unresolved state. -BEGIN; - SELECT remote_node_killer_set_event('post-prepare-transaction', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10004,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10004,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion -\echo 'COMMIT SQLSTATE' :SQLSTATE -COMMIT SQLSTATE 00000 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - ---connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - ---unresolved state shown here -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10004; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - ---this fails because heal cannot run inside txn block -BEGIN; - SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -ERROR: remote_txn_heal_data_node cannot run inside a transaction block -COMMIT; -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -select count(*) from _timescaledb_catalog.remote_txn; - count -------- - 1 -(1 row) - ---this resolves the previous txn -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10004; - count -------- - 1 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---cleanup also happened -select count(*) from _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - -BEGIN; - SELECT remote_node_killer_set_event('pre-commit-prepared', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion -\echo 'COMMIT SQLSTATE' :SQLSTATE -COMMIT SQLSTATE 00000 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - ---unresolved state shown here -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10006; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - ---this resolves the previous txn -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10006; - count -------- - 1 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -select count(*) from _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -BEGIN; - SELECT remote_node_killer_set_event('waiting-commit-prepared','loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - debug_waitpoint_enable ------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion -\echo 'COMMIT SQLSTATE' :SQLSTATE -COMMIT SQLSTATE 00000 -SELECT debug_waitpoint_release('remote_conn_xact_end'); - debug_waitpoint_release -------------------------- - -(1 row) - ---at this point the commit prepared might or might not have been executed before ---the data node process was killed. ---but in any case, healing the server will bring it into a known state -SELECT count(*) FROM _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - count -------- - 1 -(1 row) - ---heal does not use the connection cache, so unaffected -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10005; - count -------- - 1 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -select count(*) from _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - ---test prepare transactions. Note that leaked prepared stmts should be ---detected by `remote_txn_check_for_leaked_prepared_statements` so we ---should be fine if we don't see any WARNINGS. -BEGIN; - SELECT test.remote_exec('{loopback}', $$ PREPARE prep_1 AS SELECT 1 $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: PREPARE prep_1 AS SELECT 1 - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" -COMMIT; ---unique constraint violation, connection should remain -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -BEGIN; - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback}', $$ PREPARE prep_1 AS SELECT 1 $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: PREPARE prep_1 AS SELECT 1 - remote_exec -------------- - -(1 row) - - --connection in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 2 | f -(1 row) - - --generate a unique violation - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" - ROLLBACK TO SAVEPOINT save_1; - --for correctness, the connection must remain after rollback since - --the transaction is still ongoing - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (81,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (81,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" -COMMIT; ---connection should remain and be idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 81; - count -------- - 1 -(1 row) - ---Make the primary key DEFERRABLE and INITIALLY DEFERRED ---this is a way to force errors to happen during PREPARE TRANSACTION ---since pkey constraint violations would not occur on the INSERT command ---but rather are deferred till PREPARE TRANSACTION happens. -ALTER TABLE "S 1"."T 1" DROP CONSTRAINT t1_pkey, -ADD CONSTRAINT t1_pkey PRIMARY KEY ("C 1") DEFERRABLE INITIALLY DEFERRED; ---test ROLLBACK TRANSACTION on failure in PREPARE TRANSACTION. --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f -(1 row) - -COMMIT; -ERROR: [loopback]: duplicate key value violates unique constraint "t1_pkey" -RESET client_min_messages; ---connection should be removed since PREPARE TRANSACTION failed -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---test ROLLBACK TRANSACTION ---this has an error on the second connection. So should force conn1 to prepare transaction ---ok and then have the txn fail on conn2. Thus conn1 would do a ROLLBACK PREPARED. ---conn2 would do a ROLLBACK TRANSACTION. --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10010,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - --Both connections in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f - loopback2 | OK | INTRANS | 1 | f -(2 rows) - -COMMIT; -ERROR: [loopback2]: duplicate key value violates unique constraint "t1_pkey" -RESET client_min_messages; ---one connection should remain and be idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10010; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - --- Below will fail the abort and thus ROLLBACK TRANSACTION will never --- be called leaving a prepared_xact that should be rolled back by --- heal server. --- --- We set min message level to "error" since different warnings can be --- generated due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('pre-abort', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10011,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f - loopback2 | OK | INTRANS | 1 | f -(2 rows) - -COMMIT; -ERROR: [loopback2]: duplicate key value violates unique constraint "t1_pkey" -RESET client_min_messages; ---failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10011; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10011; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---heal is not using the connection cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ -(0 rows) - ---test simple subtrans abort. -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10012,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10012,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10013,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback2]: INSERT INTO "S 1"."T 1" VALUES (10013,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f - loopback2 | OK | INTRANS | 1 | f -(2 rows) - - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback2]: INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f - loopback2 | OK | INTRANS | 2 | f -(2 rows) - - ROLLBACK TO SAVEPOINT save_1; - -- For correctness, both connections should remain in order to - -- continue the transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 1 | f - loopback2 | OK | INTRANS | 1 | f -(2 rows) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10014,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10014,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10015,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback2]: INSERT INTO "S 1"."T 1" VALUES (10015,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 2 | f - loopback2 | OK | INTRANS | 2 | f -(2 rows) - -COMMIT; -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | IDLE | 0 | f - loopback2 | OK | IDLE | 0 | f -(2 rows) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" > 10011; - count -------- - 4 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - --- Test comm error in subtrans abort --- --- We set min message level to "error" since different warnings can be --- generated due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('subxact-abort', 'loopback'); - remote_node_killer_set_event ------------------------------- - -(1 row) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10017,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10018,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - remote_exec -------------- - -(1 row) - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | OK | INTRANS | 2 | f - loopback2 | OK | INTRANS | 1 | f -(2 rows) - - ROLLBACK TO SAVEPOINT save_1; - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback | BAD | UNKNOWN | 1 | t - loopback2 | OK | INTRANS | 1 | f -(2 rows) - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10019,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -ERROR: connection to data node "loopback" was lost - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10020,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -ERROR: current transaction is aborted, commands ignored until end of transaction block -COMMIT; -RESET client_min_messages; -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - node_name | connection_status | transaction_status | transaction_depth | processing ------------+-------------------+--------------------+-------------------+------------ - loopback2 | OK | IDLE | 0 | f -(1 row) - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" > 10016; - count -------- - 0 -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - ---block preparing transactions on the frontend -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10051,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -WARNING: executing remote command is deprecated -NOTICE: [loopback]: INSERT INTO "S 1"."T 1" VALUES (10051,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') - remote_exec -------------- - -(1 row) - -PREPARE TRANSACTION 'test-1'; -ERROR: cannot prepare a transaction that modified remote tables --- test remote_txn cleanup on data node delete --- -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback' or data_node_name = 'loopback2'; - count -------- - 2 -(1 row) - -SELECT * FROM delete_data_node('loopback'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback'; - count -------- - 0 -(1 row) - -SELECT * FROM delete_data_node('loopback2'); -WARNING: deleting data node is deprecated - delete_data_node ------------------- - t -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback2'; - count -------- - 0 -(1 row) - diff --git a/tsl/test/expected/remote_txn_id.out b/tsl/test/expected/remote_txn_id.out deleted file mode 100644 index d67b921b1f0..00000000000 --- a/tsl/test/expected/remote_txn_id.out +++ /dev/null @@ -1,56 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER -CREATE FUNCTION _timescaledb_functions.test_remote_txn_id() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_id' -LANGUAGE C STRICT; -SELECT _timescaledb_functions.test_remote_txn_id(); - test_remote_txn_id --------------------- - -(1 row) - -SELECT 'ts-1-10-20-30'::rxid; - rxid ---------------- - ts-1-10-20-30 -(1 row) - -create table tbl_w_rxid( - txn_id rxid -); -CREATE UNIQUE INDEX idx_name ON tbl_w_rxid ((txn_id::text)); -INSERT INTO tbl_w_rxid VALUES ('ts-1-10-20-30'), ('ts-1-11-20-30'), ('ts-1-10-21-30'); -SELECT txn_id, _timescaledb_functions.rxid_in(_timescaledb_functions.rxid_out(txn_id))::text = txn_id::text FROM tbl_w_rxid; - txn_id | ?column? ----------------+---------- - ts-1-10-20-30 | t - ts-1-11-20-30 | t - ts-1-10-21-30 | t -(3 rows) - -\set ON_ERROR_STOP 0 -INSERT INTO tbl_w_rxid VALUES ('ts-1-10-20-30'); -ERROR: duplicate key value violates unique constraint "idx_name" -SELECT ''::rxid; -ERROR: invalid input syntax for remote transaction ID: '' at character 8 -SELECT '---'::rxid; -ERROR: invalid input syntax for remote transaction ID: '---' at character 8 -SELECT '----'::rxid; -ERROR: invalid input syntax for remote transaction ID: '----' at character 8 -SELECT 'ts---'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts---' at character 8 -SELECT 'ts----'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts----' at character 8 -SELECT 'ts-1-10-20a'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts-1-10-20a' at character 8 -SELECT 'ts-2-10-20-40'::rxid; -ERROR: invalid version for remote transaction ID: 2 at character 8 -SELECT 'ts-1-10-20.0'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts-1-10-20.0' at character 8 -SELECT 'ts-1-10.0-20'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts-1-10.0-20' at character 8 -SELECT 'ts-a1-10-20-8'::rxid; -ERROR: invalid input syntax for remote transaction ID: 'ts-a1-10-20-8' at character 8 diff --git a/tsl/test/expected/remote_txn_resolve.out b/tsl/test/expected/remote_txn_resolve.out deleted file mode 100644 index d1e46bda8bd..00000000000 --- a/tsl/test/expected/remote_txn_resolve.out +++ /dev/null @@ -1,401 +0,0 @@ --- 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. -\c :TEST_DBNAME :ROLE_SUPERUSER -CREATE OR REPLACE FUNCTION create_records() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records' -LANGUAGE C; -CREATE OR REPLACE FUNCTION create_prepared_record() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_prepared_record' -LANGUAGE C; -CREATE OR REPLACE FUNCTION create_records_with_concurrent_heal() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records_with_concurrent_heal' -LANGUAGE C; -CREATE OR REPLACE FUNCTION add_loopback_server( - server_name NAME, - host TEXT = 'localhost', - database NAME = current_database(), - port INTEGER = inet_server_port(), - if_not_exists BOOLEAN = FALSE, - bootstrap BOOLEAN = TRUE, - password TEXT = NULL -) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME, - server_created BOOL, database_created BOOL, extension_created BOOL) -AS :TSL_MODULE_PATHNAME, 'ts_unchecked_add_data_node' -LANGUAGE C; -SELECT database FROM add_loopback_server('loopback', database => :'TEST_DBNAME', bootstrap => false); -WARNING: adding data node is deprecated - database ------------------------ - db_remote_txn_resolve -(1 row) - -SELECT database FROM add_loopback_server('loopback2', database => :'TEST_DBNAME', bootstrap => false); -WARNING: adding data node is deprecated - database ------------------------ - db_remote_txn_resolve -(1 row) - -SELECT database FROM add_loopback_server('loopback3', database => :'TEST_DBNAME', bootstrap => false); -WARNING: adding data node is deprecated - database ------------------------ - db_remote_txn_resolve -(1 row) - -create table table_modified_by_txns ( - describes text -); ---create records will create 3 records ---1) that is committed ---2) that is prepared but not committed ---3) that is prepared and rolled back ---Thus (1) will be seen right away, (2) will be seen after the heal, (3) will never be seen -SELECT create_records(); - create_records ----------------- - -(1 row) - -SELECT * FROM table_modified_by_txns; - describes ------------ - committed -(1 row) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 3 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT * FROM table_modified_by_txns; - describes ------------------------- - committed - prepared not committed -(2 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - ---insert one record where the heal function is run concurrently during different steps of the process ---this tests safety when, for example, the heal function is run while the frontend txn is still ongoing. -SELECT create_records_with_concurrent_heal(); - create_records_with_concurrent_heal -------------------------------------- - -(1 row) - -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal -(3 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 1 -(1 row) - -SELECT create_records(); - create_records ----------------- - -(1 row) - --- create an additional prepared entry. This will allow us to test heal behavior when one --- attempt errors out and when the other should succeed. The debug_inject_gid_error logic --- only induces one error for now. This can be modified later as desired via another --- session variable. -SELECT create_prepared_record(); - create_prepared_record ------------------------- - -(1 row) - ---inject errors in the GID and test "commit" resolution for it -SET timescaledb.debug_inject_gid_error TO 'commit'; ---heal should error out and the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -WARNING: could not commit prepared transaction on data node "loopback2" - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal - committed - prepared not committed -(5 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 4 -(1 row) - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); - create_prepared_record ------------------------- - -(1 row) - ---inject errors in the GID and test "abort" resolution for it -SET timescaledb.debug_inject_gid_error TO 'abort'; ---heal should error out and the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -WARNING: could not roll back prepared transaction on data node "loopback2" - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal - committed - prepared not committed - prepared not committed -(6 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 4 -(1 row) - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); - create_prepared_record ------------------------- - -(1 row) - ---test "inprogress" resolution for the prepared 2PC -SET timescaledb.debug_inject_gid_error TO 'inprogress'; ---heal will not error out but the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); - remote_txn_heal_data_node ---------------------------- - 1 -(1 row) - -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal - committed - prepared not committed - prepared not committed - prepared not committed -(7 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 1 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 4 -(1 row) - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); - create_prepared_record ------------------------- - -(1 row) - ---set to any random value so that it does not have any effect and allows healing -SET timescaledb.debug_inject_gid_error TO 'ignored'; -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 2 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal - committed - prepared not committed - prepared not committed - prepared not committed - prepared not committed - prepared not committed -(9 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - ---test that it is safe to have non-ts prepared-txns with heal -BEGIN; - INSERT INTO public.table_modified_by_txns VALUES ('non-ts-txn'); -PREPARE TRANSACTION 'non-ts-txn'; -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -NOTICE: skipping 1 non-TimescaleDB prepared transaction - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -NOTICE: skipping 1 non-TimescaleDB prepared transaction - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); -NOTICE: skipping 1 non-TimescaleDB prepared transaction - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -COMMIT PREPARED 'non-ts-txn'; -SELECT * FROM table_modified_by_txns; - describes --------------------------------- - committed - prepared not committed - committed with concurrent heal - committed - prepared not committed - prepared not committed - prepared not committed - prepared not committed - prepared not committed - non-ts-txn -(10 rows) - -SELECT count(*) FROM pg_prepared_xacts; - count -------- - 0 -(1 row) - -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - count -------- - 0 -(1 row) - --- test that healing function does not conflict with other databases --- --- #3433 --- create additional database and simulate remote txn activity -CREATE DATABASE test_an2; -\c test_an2 -BEGIN; -CREATE TABLE unused(id int); -PREPARE TRANSACTION 'ts-1-10-20-30'; -\c :TEST_DBNAME :ROLE_SUPERUSER --- should not fail -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - remote_txn_heal_data_node ---------------------------- - 0 -(1 row) - -\c test_an2 -ROLLBACK PREPARED 'ts-1-10-20-30'; -\c :TEST_DBNAME :ROLE_SUPERUSER -DROP DATABASE test_an2 WITH (FORCE); diff --git a/tsl/test/isolation/expected/cagg_concurrent_refresh_dist_ht.out b/tsl/test/isolation/expected/cagg_concurrent_refresh_dist_ht.out deleted file mode 100644 index c4d3b3d9a17..00000000000 --- a/tsl/test/isolation/expected/cagg_concurrent_refresh_dist_ht.out +++ /dev/null @@ -1,600 +0,0 @@ -Parsed test spec with 8 sessions - -starting permutation: R1_refresh S1_select R3_refresh S1_select L2_read_unlock_threshold_table L3_unlock_cagg_table L1_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 -(7 rows) - -cagg_bucket_count ------------------ - 7 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 70 -(1 row) - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(10 rows) - -cagg_bucket_count ------------------ - 10 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L2_read_unlock_threshold_table: - ROLLBACK; - -step L3_unlock_cagg_table: - ROLLBACK; - -step L1_unlock_threshold_table: - ROLLBACK; - - -starting permutation: L2_read_lock_threshold_table R3_refresh L2_read_unlock_threshold_table S1_select L3_unlock_cagg_table L1_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step L2_read_lock_threshold_table: - LOCK _timescaledb_catalog.continuous_aggs_invalidation_threshold - IN ACCESS SHARE MODE; - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step L2_read_unlock_threshold_table: - ROLLBACK; - -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(6 rows) - -cagg_bucket_count ------------------ - 6 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L3_unlock_cagg_table: - ROLLBACK; - -step L1_unlock_threshold_table: - ROLLBACK; - - -starting permutation: R1_refresh L2_read_lock_threshold_table R3_refresh L2_read_unlock_threshold_table S1_select L3_unlock_cagg_table L1_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step L2_read_lock_threshold_table: - LOCK _timescaledb_catalog.continuous_aggs_invalidation_threshold - IN ACCESS SHARE MODE; - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step L2_read_unlock_threshold_table: - ROLLBACK; - -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(10 rows) - -cagg_bucket_count ------------------ - 10 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L3_unlock_cagg_table: - ROLLBACK; - -step L1_unlock_threshold_table: - ROLLBACK; - - -starting permutation: R3_refresh L2_read_lock_threshold_table R1_refresh L2_read_unlock_threshold_table S1_select L3_unlock_cagg_table L1_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step L2_read_lock_threshold_table: - LOCK _timescaledb_catalog.continuous_aggs_invalidation_threshold - IN ACCESS SHARE MODE; - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step L2_read_unlock_threshold_table: - ROLLBACK; - -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(10 rows) - -cagg_bucket_count ------------------ - 10 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L3_unlock_cagg_table: - ROLLBACK; - -step L1_unlock_threshold_table: - ROLLBACK; - - -starting permutation: L3_lock_cagg_table R1_refresh L3_unlock_cagg_table S1_select L1_unlock_threshold_table L2_read_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step L3_lock_cagg_table: - SELECT lock_cagg('cond_10'); - -lock_cagg ---------- - -(1 row) - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step L3_unlock_cagg_table: - ROLLBACK; - -step R1_refresh: <... completed> -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 -(7 rows) - -cagg_bucket_count ------------------ - 7 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 70 -(1 row) - -step L1_unlock_threshold_table: - ROLLBACK; - -step L2_read_unlock_threshold_table: - ROLLBACK; - - -starting permutation: L3_lock_cagg_table R1_refresh R2_refresh L3_unlock_cagg_table S1_select L1_unlock_threshold_table L2_read_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step L3_lock_cagg_table: - SELECT lock_cagg('cond_10'); - -lock_cagg ---------- - -(1 row) - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step R2_refresh: - CALL refresh_continuous_aggregate('cond_10', 35, 62); - -step L3_unlock_cagg_table: - ROLLBACK; - -step R1_refresh: <... completed> -R2: NOTICE: continuous aggregate "cond_10" is already up-to-date -step R2_refresh: <... completed> -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 -(7 rows) - -cagg_bucket_count ------------------ - 7 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 70 -(1 row) - -step L1_unlock_threshold_table: - ROLLBACK; - -step L2_read_unlock_threshold_table: - ROLLBACK; - - -starting permutation: L3_lock_cagg_table R1_refresh R3_refresh L3_unlock_cagg_table S1_select L1_unlock_threshold_table L2_read_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step L3_lock_cagg_table: - SELECT lock_cagg('cond_10'); - -lock_cagg ---------- - -(1 row) - -step R1_refresh: - CALL refresh_continuous_aggregate('cond_10', 25, 70); - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step L3_unlock_cagg_table: - ROLLBACK; - -step R1_refresh: <... completed> -step R3_refresh: <... completed> -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 30| 18.3 - 40|16.0909090909091 - 50| 26.9 - 60| 18.9 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(10 rows) - -cagg_bucket_count ------------------ - 10 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L1_unlock_threshold_table: - ROLLBACK; - -step L2_read_unlock_threshold_table: - ROLLBACK; - - -starting permutation: L3_lock_cagg_table R3_refresh R4_refresh L3_unlock_cagg_table S1_select L1_unlock_threshold_table L2_read_unlock_threshold_table -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step L3_lock_cagg_table: - SELECT lock_cagg('cond_10'); - -lock_cagg ---------- - -(1 row) - -step R3_refresh: - CALL refresh_continuous_aggregate('cond_10', 70, 107); - -step R4_refresh: - CALL refresh_continuous_aggregate('cond_20', 39, 84); - -step L3_unlock_cagg_table: - ROLLBACK; - -step R3_refresh: <... completed> -step S1_select: - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; - -bucket| avg_temp -------+---------------- - 0|15.8888888888889 - 10| 14.2 - 20| 13.4 - 70| 24.6 - 80| 23.6 - 90| 21.3 -(6 rows) - -cagg_bucket_count ------------------ - 6 -(1 row) - -hypertable|threshold -----------+--------- -conditions| 100 -(1 row) - -step L1_unlock_threshold_table: - ROLLBACK; - -step L2_read_unlock_threshold_table: - ROLLBACK; - diff --git a/tsl/test/isolation/expected/cagg_drop_chunks_iso.out b/tsl/test/isolation/expected/cagg_drop_chunks_iso.out deleted file mode 100644 index 0021c2ce702..00000000000 --- a/tsl/test/isolation/expected/cagg_drop_chunks_iso.out +++ /dev/null @@ -1,70 +0,0 @@ -Parsed test spec with 3 sessions - -starting permutation: T1_select L_enable_chunks_locked T1_drop_chunks T2_insert_1 T2_insert_2 L_release_chunks_locked T1_refresh T1_select -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step T1_select: SELECT * FROM cond_summary ORDER BY bucket; -bucket |avg_temp -----------------------------+-------- -Fri Nov 30 16:00:00 2018 PST| 0 -Sat Dec 01 16:00:00 2018 PST| 0 -Sun Dec 02 16:00:00 2018 PST| 0 -(3 rows) - -step L_enable_chunks_locked: SELECT debug_waitpoint_enable('drop_chunks_locked'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step T1_drop_chunks: SELECT count(*) FROM drop_chunks('conditions', older_than => '2018-12-03 00:00'::timestamptz); -step T2_insert_1: - INSERT INTO conditions - SELECT generate_series('2018-12-04 12:00'::timestamptz, '2018-12-05 12:00','1 day'), 10; - -step T2_insert_2: - INSERT INTO conditions - SELECT generate_series('2018-12-01 12:00'::timestamptz, '2018-12-03 12:00','1 day'), 100; - -step L_release_chunks_locked: SELECT debug_waitpoint_release('drop_chunks_locked'); -debug_waitpoint_release ------------------------ - -(1 row) - -step T1_drop_chunks: <... completed> -count ------ - 2 -(1 row) - -step T2_insert_2: <... completed> -step T1_refresh: CALL refresh_continuous_aggregate('cond_summary', NULL, NULL); -step T1_select: SELECT * FROM cond_summary ORDER BY bucket; -bucket |avg_temp -----------------------------+-------- -Fri Nov 30 16:00:00 2018 PST| 100 -Sat Dec 01 16:00:00 2018 PST| 100 -Sun Dec 02 16:00:00 2018 PST| 50 -Mon Dec 03 16:00:00 2018 PST| 10 -Tue Dec 04 16:00:00 2018 PST| 10 -(5 rows) - diff --git a/tsl/test/isolation/expected/cagg_multi_dist_ht.out b/tsl/test/isolation/expected/cagg_multi_dist_ht.out deleted file mode 100644 index 69892badd92..00000000000 --- a/tsl/test/isolation/expected/cagg_multi_dist_ht.out +++ /dev/null @@ -1,265 +0,0 @@ -Parsed test spec with 10 sessions - -starting permutation: Setup2 LockMat1 Refresh1 Refresh2 UnlockMat1 TearD1 TearD2 -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step Setup2: - CREATE MATERIALIZED VIEW continuous_view_1( bkt, cnt) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), COUNT(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW continuous_view_2(bkt, maxl) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), max(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE FUNCTION lock_mattable(schema_name TEXT, table_name TEXT) RETURNS void AS $$ - BEGIN EXECUTE format('LOCK TABLE %I.%I', schema_name, table_name); - END; $$ LANGUAGE plpgsql; - -step LockMat1: BEGIN; select lock_mattable(materialization_hypertable_schema, materialization_hypertable_name) FROM ( SELECT materialization_hypertable_schema, materialization_hypertable_name from timescaledb_information.continuous_aggregates where view_name::text like 'continuous_view_1') q ; - -lock_mattable -------------- - -(1 row) - -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step UnlockMat1: ROLLBACK; -step Refresh1: <... completed> -step TearD1: - DROP FUNCTION lock_mattable(TEXT, TEXT); - -step TearD2: - DROP TABLE ts_continuous_test CASCADE; - - -starting permutation: Setup2 Refresh1 Refresh2 LockMat1 I1 Refresh1 Refresh2 UnlockMat1 Refresh1_sel Refresh2_sel TearD1 TearD2 -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step Setup2: - CREATE MATERIALIZED VIEW continuous_view_1( bkt, cnt) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), COUNT(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW continuous_view_2(bkt, maxl) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), max(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE FUNCTION lock_mattable(schema_name TEXT, table_name TEXT) RETURNS void AS $$ - BEGIN EXECUTE format('LOCK TABLE %I.%I', schema_name, table_name); - END; $$ LANGUAGE plpgsql; - -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step LockMat1: BEGIN; select lock_mattable(materialization_hypertable_schema, materialization_hypertable_name) FROM ( SELECT materialization_hypertable_schema, materialization_hypertable_name from timescaledb_information.continuous_aggregates where view_name::text like 'continuous_view_1') q ; - -lock_mattable -------------- - -(1 row) - -step I1: INSERT INTO ts_continuous_test SELECT 0, i*10 FROM (SELECT generate_series(0, 10) AS i) AS i; -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step UnlockMat1: ROLLBACK; -step Refresh1: <... completed> -step Refresh1_sel: select * from continuous_view_1 where bkt = 0 or bkt > 30 -bkt|cnt ----+--- - 0| 16 -(1 row) - -step Refresh2_sel: select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; -bkt|maxl ----+---- - 0| 100 -(1 row) - -step TearD1: - DROP FUNCTION lock_mattable(TEXT, TEXT); - -step TearD2: - DROP TABLE ts_continuous_test CASCADE; - - -starting permutation: Setup2 Refresh1 Refresh2 Refresh1_sel Refresh2_sel LockMat1 I2 Refresh1 Refresh2 UnlockMat1 Refresh1_sel Refresh2_sel TearD1 TearD2 -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step Setup2: - CREATE MATERIALIZED VIEW continuous_view_1( bkt, cnt) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), COUNT(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW continuous_view_2(bkt, maxl) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), max(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE FUNCTION lock_mattable(schema_name TEXT, table_name TEXT) RETURNS void AS $$ - BEGIN EXECUTE format('LOCK TABLE %I.%I', schema_name, table_name); - END; $$ LANGUAGE plpgsql; - -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step Refresh1_sel: select * from continuous_view_1 where bkt = 0 or bkt > 30 -bkt|cnt ----+--- - 0| 5 -(1 row) - -step Refresh2_sel: select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; -bkt|maxl ----+---- - 0| 4 -(1 row) - -step LockMat1: BEGIN; select lock_mattable(materialization_hypertable_schema, materialization_hypertable_name) FROM ( SELECT materialization_hypertable_schema, materialization_hypertable_name from timescaledb_information.continuous_aggregates where view_name::text like 'continuous_view_1') q ; - -lock_mattable -------------- - -(1 row) - -step I2: INSERT INTO ts_continuous_test SELECT 40, 1000 ; -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step UnlockMat1: ROLLBACK; -R1: NOTICE: continuous aggregate "continuous_view_1" is already up-to-date -step Refresh1: <... completed> -step Refresh1_sel: select * from continuous_view_1 where bkt = 0 or bkt > 30 -bkt|cnt ----+--- - 0| 5 -(1 row) - -step Refresh2_sel: select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; -bkt|maxl ----+---- - 0| 4 - 40|1000 -(2 rows) - -step TearD1: - DROP FUNCTION lock_mattable(TEXT, TEXT); - -step TearD2: - DROP TABLE ts_continuous_test CASCADE; - - -starting permutation: Setup2 Refresh1 Refresh2 Refresh1_sel Refresh2_sel U1 U2 LInvRow Refresh1 Refresh2 UnlockInvRow Refresh1_sel Refresh2_sel TearD1 TearD2 -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -step Setup2: - CREATE MATERIALIZED VIEW continuous_view_1( bkt, cnt) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), COUNT(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW continuous_view_2(bkt, maxl) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), max(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE FUNCTION lock_mattable(schema_name TEXT, table_name TEXT) RETURNS void AS $$ - BEGIN EXECUTE format('LOCK TABLE %I.%I', schema_name, table_name); - END; $$ LANGUAGE plpgsql; - -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step Refresh1_sel: select * from continuous_view_1 where bkt = 0 or bkt > 30 -bkt|cnt ----+--- - 0| 5 -(1 row) - -step Refresh2_sel: select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; -bkt|maxl ----+---- - 0| 4 -(1 row) - -step U1: update ts_continuous_test SET val = 5555 where time < 10; -step U2: update ts_continuous_test SET val = 5 where time > 15 and time < 25; -step LInvRow: BEGIN; update _timescaledb_catalog.continuous_aggs_invalidation_threshold set watermark = 20 where hypertable_id in ( select raw_hypertable_id from _timescaledb_catalog.continuous_agg where user_view_name like 'continuous_view_1' ); - -step Refresh1: CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); -step Refresh2: CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); -step UnlockInvRow: ROLLBACK; -step Refresh1: <... completed> -step Refresh2: <... completed> -step Refresh1_sel: select * from continuous_view_1 where bkt = 0 or bkt > 30 -bkt|cnt ----+--- - 0| 5 -(1 row) - -step Refresh2_sel: select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; -bkt|maxl ----+---- - 0|5555 -(1 row) - -step TearD1: - DROP FUNCTION lock_mattable(TEXT, TEXT); - -step TearD2: - DROP TABLE ts_continuous_test CASCADE; - diff --git a/tsl/test/isolation/expected/dist_cmd_exec.out b/tsl/test/isolation/expected/dist_cmd_exec.out deleted file mode 100644 index c2a3f7746ec..00000000000 --- a/tsl/test/isolation/expected/dist_cmd_exec.out +++ /dev/null @@ -1,64 +0,0 @@ -Parsed test spec with 2 sessions - -starting permutation: s1_lock1 s1_lock2 s2_set_search_path s2_analyze s1_invalidate s1_unlock1 s1_invalidate s1_unlock2 -node_name ------------ -data_node_1 -(1 row) - -created -------- -t -(1 row) - -step s1_lock1: SELECT debug_waitpoint_enable('dist_cmd_using_search_path_1'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_lock2: SELECT debug_waitpoint_enable('dist_cmd_using_search_path_2'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s2_set_search_path: - SET search_path = dist_schema; - SHOW search_path; - -search_path ------------ -dist_schema -(1 row) - -step s2_analyze: ANALYZE disttable; -step s1_invalidate: - SELECT invalidate_data_node('data_node_1'); - -invalidate_data_node --------------------- -f -(1 row) - -step s1_unlock1: SELECT debug_waitpoint_release('dist_cmd_using_search_path_1'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_invalidate: - SELECT invalidate_data_node('data_node_1'); - -invalidate_data_node --------------------- -f -(1 row) - -step s1_unlock2: SELECT debug_waitpoint_release('dist_cmd_using_search_path_2'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s2_analyze: <... completed> diff --git a/tsl/test/isolation/expected/dist_ha_chunk_drop.out b/tsl/test/isolation/expected/dist_ha_chunk_drop.out deleted file mode 100644 index 47fc24de146..00000000000 --- a/tsl/test/isolation/expected/dist_ha_chunk_drop.out +++ /dev/null @@ -1,61 +0,0 @@ -Parsed test spec with 3 sessions - -starting permutation: s1_init s1_set_unavailable s3_lock_enable s1_insert s2_insert s3_lock_release s1_set_available -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -node_name ------------ -data_node_4 -(1 row) - -created -------- -t -(1 row) - -step s1_init: INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:00:00'::timestamp, '2021-08-17 00:00:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(1, 500) d; -s1: WARNING: altering data node is deprecated -DETAIL: Multi-node is deprecated and will be removed in future releases. -step s1_set_unavailable: SELECT alter_data_node('data_node_4', available=>false); -alter_data_node --------------------------------------- -(data_node_4,localhost,55432,cdha_4,f) -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('chunk_data_node_delete'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_insert: INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:01:00'::timestamp, '2021-08-17 00:01:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(1, 249) d; -step s2_insert: INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:01:00'::timestamp, '2021-08-17 00:01:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(250, 499) d; -step s3_lock_release: SELECT debug_waitpoint_release('chunk_data_node_delete'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_insert: <... completed> -step s2_insert: <... completed> -s1: WARNING: altering data node is deprecated -DETAIL: Multi-node is deprecated and will be removed in future releases. -step s1_set_available: SELECT alter_data_node('data_node_4', available=>true); -alter_data_node --------------------------------------- -(data_node_4,localhost,55432,cdha_4,t) -(1 row) - diff --git a/tsl/test/isolation/expected/dist_restore_point.out b/tsl/test/isolation/expected/dist_restore_point.out deleted file mode 100644 index 72d7963c484..00000000000 --- a/tsl/test/isolation/expected/dist_restore_point.out +++ /dev/null @@ -1,388 +0,0 @@ -Parsed test spec with 3 sessions - -starting permutation: s3_lock_enable s1_create_dist_rp s2_insert s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s2_insert: INSERT INTO disttable VALUES ('2019-08-02 10:45', 0, 0.0); -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_insert: <... completed> - -starting permutation: s2_begin s2_insert s3_lock_enable s1_create_dist_rp s3_lock_count s2_commit s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s2_begin: BEGIN; -step s2_insert: INSERT INTO disttable VALUES ('2019-08-02 10:45', 0, 0.0); -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 1 -(1 row) - -step s2_commit: COMMIT; -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_commit: <... completed> - -starting permutation: s3_lock_enable s1_create_dist_rp s2_create_dist_rp s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s2_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s2_test'); -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - - -starting permutation: s3_lock_enable s1_create_dist_rp s2_dist_exec s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s2_dist_exec: CALL distributed_exec('SELECT true;', transactional => true); -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_dist_exec: <... completed> - -starting permutation: s3_lock_enable s1_create_dist_rp s2_create_dist_ht s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s2_create_dist_ht: - CREATE TABLE disttable2(time timestamptz NOT NULL, device int, temp float); - SELECT created FROM create_distributed_hypertable('disttable2', 'time', 'device'); - -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_create_dist_ht: <... completed> -created -------- -t -(1 row) - - -starting permutation: s3_lock_enable s1_create_dist_rp s2_drop_dist_ht s3_lock_count s3_lock_release -delete_data_node ----------------- -t -(1 row) - -node_name ------------ -data_node_1 -(1 row) - -node_name ------------ -data_node_2 -(1 row) - -node_name ------------ -data_node_3 -(1 row) - -created -------- -t -(1 row) - -step s3_lock_enable: SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_dist_rp: SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); -step s2_drop_dist_ht: DROP TABLE disttable2; -step s3_lock_count: - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; - -cdrp_locks|remote_txn_locks -----------+---------------- - 2| 2 -(1 row) - -step s3_lock_release: SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_dist_rp: <... completed> -valid_lsn ---------- -t -t -t -t -(4 rows) - -step s2_drop_dist_ht: <... completed> diff --git a/tsl/test/isolation/expected/dist_su_copy_chunk.out b/tsl/test/isolation/expected/dist_su_copy_chunk.out deleted file mode 100644 index c3e662e59f3..00000000000 --- a/tsl/test/isolation/expected/dist_su_copy_chunk.out +++ /dev/null @@ -1,126 +0,0 @@ -Parsed test spec with 3 sessions - -starting permutation: s1_wait1 s2_copy1 s3_check1 s3_check2 s3_check3 s1_release1 s3_check2 -node_name ---------- -dn_1 -(1 row) - -node_name ---------- -dn_2 -(1 row) - -step s1_wait1: SELECT debug_waitpoint_enable('chunk_copy_after_empty_chunk'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s2_copy1: - CALL timescaledb_experimental.move_chunk(chunk=>'public._dist_hyper_X_X_chunk', source_node=> 'dn_1', destination_node => 'dn_2') - -s3: NOTICE: [dn_1]: - SELECT 1 FROM pg_catalog.pg_tables WHERE schemaname = 'public' AND tablename = - '_dist_hyper_X_X_chunk' AND tableowner != 'htowner1' -s3: NOTICE: [dn_1]: -?column? --------- -(0 rows) - - -s3: NOTICE: [dn_2]: - SELECT 1 FROM pg_catalog.pg_tables WHERE schemaname = 'public' AND tablename = - '_dist_hyper_X_X_chunk' AND tableowner != 'htowner1' -s3: NOTICE: [dn_2]: -?column? --------- - 1 -(1 row) - - -step s3_check1: - SELECT * FROM remote_exec(ARRAY['dn_1', 'dn_2'], $DIST$ - SELECT 1 FROM pg_catalog.pg_tables WHERE schemaname = 'public' AND tablename = - '_dist_hyper_X_X_chunk' AND tableowner != 'htowner1'; $DIST$); - -remote_exec ------------ - -(1 row) - -s3: NOTICE: [dn_1]: - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk') -s3: NOTICE: [dn_1]: -usesuper --------- -f -(1 row) - - -s3: NOTICE: [dn_2]: - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk') -s3: NOTICE: [dn_2]: -usesuper --------- -t -(1 row) - - -step s3_check2: - SELECT * FROM remote_exec(ARRAY['dn_1', 'dn_2'], $DIST$ - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk'); $DIST$); - -remote_exec ------------ - -(1 row) - -step s3_check3: - SET ROLE htowner1; - SELECT * FROM remote_exec(ARRAY['dn_2'], $DIST$ - CREATE INDEX ON public._dist_hyper_X_X_chunk (lower(temp)); - $DIST$); - -s3: NOTICE: [dn_2]: - CREATE INDEX ON public._dist_hyper_X_X_chunk (lower(temp)) -ERROR: [dn_2]: must be owner of table _dist_hyper_X_X_chunk -step s1_release1: SELECT debug_waitpoint_release('chunk_copy_after_empty_chunk'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s2_copy1: <... completed> -s3: NOTICE: [dn_1]: - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk') -s3: NOTICE: [dn_1]: -usesuper --------- -(0 rows) - - -s3: NOTICE: [dn_2]: - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk') -s3: NOTICE: [dn_2]: -usesuper --------- -f -(1 row) - - -step s3_check2: - SELECT * FROM remote_exec(ARRAY['dn_1', 'dn_2'], $DIST$ - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_X_X_chunk'); $DIST$); - -remote_exec ------------ - -(1 row) - diff --git a/tsl/test/isolation/expected/remote_create_chunk.out b/tsl/test/isolation/expected/remote_create_chunk.out deleted file mode 100644 index e35d0655eec..00000000000 --- a/tsl/test/isolation/expected/remote_create_chunk.out +++ /dev/null @@ -1,210 +0,0 @@ -Parsed test spec with 4 sessions - -starting permutation: s4_wait_created s4_wait_found s1_create_chunk_1 s2_create_chunk_1 s3_conditions_locks s4_release_created s3_conditions_locks s4_release_found -step s4_wait_created: SELECT debug_waitpoint_enable('find_or_create_chunk_created'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s4_wait_found: SELECT debug_waitpoint_enable('find_or_create_chunk_found'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_chunk_1: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); - -step s2_create_chunk_1: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 2| 0| 1| 0 -(1 row) - -step s4_release_created: SELECT debug_waitpoint_release('find_or_create_chunk_created'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_chunk_1: <... completed> -slices |created ---------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [-9223372036854775808, 1073741823]}|t -(1 row) - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 0| 0| 0| 1 -(1 row) - -step s4_release_found: SELECT debug_waitpoint_release('find_or_create_chunk_found'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s2_create_chunk_1: <... completed> -slices |created ---------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [-9223372036854775808, 1073741823]}|f -(1 row) - - -starting permutation: s4_wait_created s4_wait_found s1_create_chunk_1 s2_create_chunk_2 s3_conditions_locks s4_release_created s3_conditions_locks s4_release_found -step s4_wait_created: SELECT debug_waitpoint_enable('find_or_create_chunk_created'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s4_wait_found: SELECT debug_waitpoint_enable('find_or_create_chunk_found'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_chunk_1: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); - -step s2_create_chunk_2: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[1073741823, 9223372036854775807])); - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 2| 0| 1| 0 -(1 row) - -step s4_release_created: SELECT debug_waitpoint_release('find_or_create_chunk_created'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_chunk_1: <... completed> -slices |created ---------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [-9223372036854775808, 1073741823]}|t -(1 row) - -step s2_create_chunk_2: <... completed> -slices |created --------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [1073741823, 9223372036854775807]}|t -(1 row) - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 0| 0| 0| 0 -(1 row) - -step s4_release_found: SELECT debug_waitpoint_release('find_or_create_chunk_found'); -debug_waitpoint_release ------------------------ - -(1 row) - - -starting permutation: s4_wait_created s1_create_chunk_1 s4_wait_start s2_create_chunk_1 s3_conditions_locks s4_release_created s3_conditions_locks s4_release_start s3_conditions_locks -step s4_wait_created: SELECT debug_waitpoint_enable('find_or_create_chunk_created'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s1_create_chunk_1: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); - -step s4_wait_start: SELECT debug_waitpoint_enable('find_or_create_chunk_start'); -debug_waitpoint_enable ----------------------- - -(1 row) - -step s2_create_chunk_1: - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 1| 1| 1| 0 -(1 row) - -step s4_release_created: SELECT debug_waitpoint_release('find_or_create_chunk_created'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s1_create_chunk_1: <... completed> -slices |created ---------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [-9223372036854775808, 1073741823]}|t -(1 row) - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 0| 1| 0| 0 -(1 row) - -step s4_release_start: SELECT debug_waitpoint_release('find_or_create_chunk_start'); -debug_waitpoint_release ------------------------ - -(1 row) - -step s2_create_chunk_1: <... completed> -slices |created ---------------------------------------------------------------------------------------------+------- -{"time": [1514764800000000, 1514851200000000], "device": [-9223372036854775808, 1073741823]}|f -(1 row) - -step s3_conditions_locks: - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; - -table_lock|at_start|at_created|at_found -----------+--------+----------+-------- - 0| 0| 0| 0 -(1 row) - diff --git a/tsl/test/isolation/specs/CMakeLists.txt b/tsl/test/isolation/specs/CMakeLists.txt index fb103b5001b..19213938314 100644 --- a/tsl/test/isolation/specs/CMakeLists.txt +++ b/tsl/test/isolation/specs/CMakeLists.txt @@ -17,10 +17,6 @@ list( deadlock_drop_chunks_compress.spec osm_range_updates_iso.spec) -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list(APPEND TEST_FILES cagg_concurrent_refresh_dist_ht.spec) -endif() - if(PG_VERSION VERSION_GREATER_EQUAL "14.0") list(APPEND TEST_FILES concurrent_decompress_update.spec) endif() @@ -42,20 +38,6 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) list(APPEND TEST_FILES deadlock_recompress_chunk.spec) endif() - if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list( - APPEND - TEST_FILES - cagg_multi_dist_ht.spec - cagg_drop_chunks_iso.spec - dist_ha_chunk_drop.spec - dist_restore_point.spec - remote_create_chunk.spec) - - list(APPEND TEST_TEMPLATES_MODULE_DEBUG dist_cmd_exec.spec.in - dist_su_copy_chunk.spec.in) - endif() - endif(CMAKE_BUILD_TYPE MATCHES Debug) # need to generate MODULE name for the .spec files diff --git a/tsl/test/isolation/specs/cagg_concurrent_refresh_dist_ht.spec b/tsl/test/isolation/specs/cagg_concurrent_refresh_dist_ht.spec deleted file mode 100644 index 338516a74fc..00000000000 --- a/tsl/test/isolation/specs/cagg_concurrent_refresh_dist_ht.spec +++ /dev/null @@ -1,311 +0,0 @@ -# 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. - -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'cdrp_1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_2', host => 'localhost', database => 'cdrp_2', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_3', host => 'localhost', database => 'cdrp_3', if_not_exists => true); } -# -# Setup prior to every permutation. -# -# We define a function 'cagg_bucket_count' to get the number of -# buckets in a continuous aggregate. We use it to verify that there -# aren't any duplicate buckets/rows inserted into the materialization -# hypertable after concurrent refreshes. Duplicate buckets are -# possible since there is no unique constraint on the GROUP BY keys in -# the materialized hypertable. -# -setup -{ - SELECT _timescaledb_functions.stop_background_workers(); - CREATE TABLE conditions(time int, temp float); - SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => 20, replication_factor => 2); - INSERT INTO conditions - SELECT t, abs(timestamp_hash(to_timestamp(t)::timestamp))%40 - FROM generate_series(1, 100, 1) t; - CREATE OR REPLACE FUNCTION cond_now() - RETURNS int LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - CALL distributed_exec($DIST$ - CREATE OR REPLACE FUNCTION cond_now() - RETURNS int LANGUAGE SQL STABLE AS - $$ - SELECT coalesce(max(time), 0) - FROM conditions - $$; - $DIST$); - - SELECT set_integer_now_func('conditions', 'cond_now'); - CREATE MATERIALIZED VIEW cond_10 - WITH (timescaledb.continuous, - timescaledb.materialized_only=true) - AS - SELECT time_bucket(10, time) AS bucket, avg(temp) AS avg_temp - FROM conditions - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW cond_20 - WITH (timescaledb.continuous, - timescaledb.materialized_only=true) - AS - SELECT time_bucket(20, time) AS bucket, avg(temp) AS avg_temp - FROM conditions - GROUP BY 1 WITH NO DATA; - - CREATE OR REPLACE FUNCTION cagg_bucket_count(cagg regclass) - RETURNS int AS - $$ - DECLARE - cagg_schema name; - cagg_name name; - cagg_hyper_schema name; - cagg_hyper_name name; - cagg_hyper_relid regclass; - result int; - BEGIN - SELECT nspname, relname - INTO cagg_schema, cagg_name - FROM pg_class c, pg_namespace n - WHERE c.oid = cagg - AND c.relnamespace = n.oid; - - SELECT format('%I.%I', h.schema_name, h.table_name)::regclass, h.schema_name, h.table_name - INTO cagg_hyper_relid, cagg_hyper_schema, cagg_hyper_name - FROM _timescaledb_catalog.continuous_agg ca, _timescaledb_catalog.hypertable h - WHERE ca.user_view_name = cagg_name - AND ca.user_view_schema = cagg_schema - AND ca.mat_hypertable_id = h.id; - - EXECUTE format('SELECT count(*) FROM %I.%I', - quote_ident(cagg_hyper_schema), - quote_ident(cagg_hyper_name)) - INTO result; - - RETURN result; - END - $$ LANGUAGE plpgsql; - CREATE OR REPLACE FUNCTION lock_cagg(cagg name) RETURNS void AS $$ - DECLARE - mattable text; - BEGIN - SELECT format('%I.%I', user_view_schema, user_view_name) - FROM _timescaledb_catalog.continuous_agg - INTO mattable; - EXECUTE format('LOCK table %s IN EXCLUSIVE MODE', mattable); - END; $$ LANGUAGE plpgsql; -} - -# Move the invalidation threshold so that we can generate some -# invalidations. This must be done in its own setup block since -# refreshing can't be done in a transaction block. -setup -{ - CALL refresh_continuous_aggregate('cond_10', 0, 30); - -} - -# Generate some invalidations. Must be done in separate transcations -# or otherwise there will be only one invalidation. -setup -{ - BEGIN; - INSERT INTO conditions - SELECT t, abs(timestamp_hash(to_timestamp(t)::timestamp))%40 - FROM generate_series(1, 10, 1) t; - COMMIT; - BEGIN; - INSERT INTO conditions - SELECT t, abs(timestamp_hash(to_timestamp(t)::timestamp))%40 - FROM generate_series(10, 20, 1) t; - COMMIT; - BEGIN; - INSERT INTO conditions - SELECT t, abs(timestamp_hash(to_timestamp(t)::timestamp))%40 - FROM generate_series(15, 40, 1) t; - COMMIT; -} - -teardown { - DROP TABLE conditions CASCADE; -} - -# Session to refresh the cond_10 continuous aggregate -session "R1" -setup -{ - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "R1_refresh" -{ - CALL refresh_continuous_aggregate('cond_10', 25, 70); -} - - -# Refresh that overlaps with R1 -session "R2" -setup -{ - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "R2_refresh" -{ - CALL refresh_continuous_aggregate('cond_10', 35, 62); -} - - -# Refresh on same aggregate (cond_10) that doesn't overlap with R1 and R2 -session "R3" -setup -{ - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "R3_refresh" -{ - CALL refresh_continuous_aggregate('cond_10', 70, 107); -} - -# Overlapping refresh on another continuous aggregate (cond_20) -session "R4" -setup -{ - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "R4_refresh" -{ - CALL refresh_continuous_aggregate('cond_20', 39, 84); -} - -# Define a number of lock sessions to simulate concurrent refreshes -# by selectively grabbing the locks we use to handle concurrency. - -# The "L1" session exclusively locks the invalidation threshold -# table. This simulates an ongoing update of the invalidation -# threshold, which has not yet finished. -session "L1" -setup -{ - BEGIN; - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "L1_unlock_threshold_table" -{ - ROLLBACK; -} - -# The "L2" session takes an access share lock on the invalidation -# threshold table. This simulates a reader, which has not yet finished -# (e.g., and insert into the hypertable, or a refresh that has not yet -# grabbed the exclusive lock). -session "L2" -setup -{ - BEGIN; - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "L2_read_lock_threshold_table" -{ - LOCK _timescaledb_catalog.continuous_aggs_invalidation_threshold - IN ACCESS SHARE MODE; -} -step "L2_read_unlock_threshold_table" -{ - ROLLBACK; -} - -# The "L3" session locks the cagg table. This simulates an ongoing -# refresh that has not yet completed and released the lock on the cagg -# materialization table. -# -session "L3" -setup -{ - BEGIN; - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "L3_lock_cagg_table" -{ - SELECT lock_cagg('cond_10'); -} -step "L3_unlock_cagg_table" -{ - ROLLBACK; -} - -# Session to view the contents of a cagg after materialization. It -# also prints the bucket count (number of rows in the materialization -# hypertable) and the invalidation threshold. The bucket count should -# match the number of rows in the query if there are no duplicate -# buckets/rows. -session "S1" -setup -{ - SET SESSION lock_timeout = '500ms'; - SET SESSION deadlock_timeout = '500ms'; -} -step "S1_select" -{ - SELECT bucket, avg_temp - FROM cond_10 - ORDER BY 1; - - SELECT * FROM cagg_bucket_count('cond_10'); - SELECT h.table_name AS hypertable, it.watermark AS threshold - FROM _timescaledb_catalog.continuous_aggs_invalidation_threshold it, - _timescaledb_catalog.hypertable h - WHERE it.hypertable_id = h.id; -} - -#################################################################### -# -# Tests for concurrent updates to the invalidation threshold (first -# transaction of a refresh). -# -#################################################################### - -# Run single transaction refresh to get some reference output. The -# result of a query on the aggregate should always look like this -# example (when refreshed with the same window). -permutation "R1_refresh" "S1_select" "R3_refresh" "S1_select" "L2_read_unlock_threshold_table" "L3_unlock_cagg_table" "L1_unlock_threshold_table" - -# A threshold reader (insert) should block a refresh if the threshold -# does not exist yet (insert of new threshold) -permutation "L2_read_lock_threshold_table" "R3_refresh" "L2_read_unlock_threshold_table" "S1_select" "L3_unlock_cagg_table" "L1_unlock_threshold_table" - -# A threshold reader (insert) should block a refresh if the threshold -# needs an update -permutation "R1_refresh" "L2_read_lock_threshold_table" "R3_refresh" "L2_read_unlock_threshold_table" "S1_select" "L3_unlock_cagg_table" "L1_unlock_threshold_table" - -# A threshold reader (insert) blocks a refresh even if the threshold -# doesn't need an update (could be improved) -permutation "R3_refresh" "L2_read_lock_threshold_table" "R1_refresh" "L2_read_unlock_threshold_table" "S1_select" "L3_unlock_cagg_table" "L1_unlock_threshold_table" - -################################################################## -# -# Tests for concurrent refreshes of continuous aggregates (second -# transaction of a refresh). -# -################################################################## - -# Interleave two refreshes that are overlapping (one simulated). Since -# we serialize refreshes, R1 should block until the lock is released -permutation "L3_lock_cagg_table" "R1_refresh" "L3_unlock_cagg_table" "S1_select" "L1_unlock_threshold_table" "L2_read_unlock_threshold_table" - -# R1 and R2 queued to refresh, both should serialize -permutation "L3_lock_cagg_table" "R1_refresh" "R2_refresh" "L3_unlock_cagg_table" "S1_select" "L1_unlock_threshold_table" "L2_read_unlock_threshold_table" - -# R1 and R3 don't have overlapping refresh windows, but should serialize -# anyway. This could potentially be optimized in the future. -permutation "L3_lock_cagg_table" "R1_refresh" "R3_refresh" "L3_unlock_cagg_table" "S1_select" "L1_unlock_threshold_table" "L2_read_unlock_threshold_table" - -# Concurrent refreshing across two different aggregates on same -# hypertable does not block -permutation "L3_lock_cagg_table" "R3_refresh" "R4_refresh" "L3_unlock_cagg_table" "S1_select" "L1_unlock_threshold_table" "L2_read_unlock_threshold_table" diff --git a/tsl/test/isolation/specs/cagg_drop_chunks_iso.spec b/tsl/test/isolation/specs/cagg_drop_chunks_iso.spec deleted file mode 100644 index 56ffccc71a3..00000000000 --- a/tsl/test/isolation/specs/cagg_drop_chunks_iso.spec +++ /dev/null @@ -1,62 +0,0 @@ -# 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. - -setup { - CREATE TABLE conditions("time" timestamptz, temp float); -} - -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'cdrp_1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_2', host => 'localhost', database => 'cdrp_2', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_3', host => 'localhost', database => 'cdrp_3', if_not_exists => true); } - -setup { - SELECT created FROM create_distributed_hypertable('conditions', 'time', chunk_time_interval => '1 day'::interval); -} - -setup { - INSERT INTO conditions - SELECT generate_series('2018-12-01 12:00'::timestamptz, '2018-12-03 12:00','1 day'), 0; -} - -setup { - CREATE MATERIALIZED VIEW cond_summary - WITH (timescaledb.continuous, timescaledb.materialized_only=true) - AS SELECT time_bucket('1 day'::interval, time) AS bucket, - avg(temp) AS avg_temp - FROM conditions - GROUP BY 1 - WITH NO DATA; -} - -setup { - CALL refresh_continuous_aggregate('cond_summary', NULL, NULL); -} - -teardown { - DROP TABLE conditions CASCADE; -} - -session "L" -step "L_enable_chunks_locked" { SELECT debug_waitpoint_enable('drop_chunks_locked'); } -step "L_release_chunks_locked" { SELECT debug_waitpoint_release('drop_chunks_locked'); } - -session "T1" -step "T1_drop_chunks" { SELECT count(*) FROM drop_chunks('conditions', older_than => '2018-12-03 00:00'::timestamptz); } -step "T1_refresh" { CALL refresh_continuous_aggregate('cond_summary', NULL, NULL); } -step "T1_select" { SELECT * FROM cond_summary ORDER BY bucket; } - -session "T2" -# This insert outside the dropped chunks -step "T2_insert_1" { - INSERT INTO conditions - SELECT generate_series('2018-12-04 12:00'::timestamptz, '2018-12-05 12:00','1 day'), 10; -} - -# This insert inside the dropped chunks -step "T2_insert_2" { - INSERT INTO conditions - SELECT generate_series('2018-12-01 12:00'::timestamptz, '2018-12-03 12:00','1 day'), 100; -} - -permutation "T1_select" "L_enable_chunks_locked" "T1_drop_chunks" "T2_insert_1" "T2_insert_2" "L_release_chunks_locked" "T1_refresh" "T1_select" diff --git a/tsl/test/isolation/specs/cagg_multi_dist_ht.spec b/tsl/test/isolation/specs/cagg_multi_dist_ht.spec deleted file mode 100644 index 844976db5e0..00000000000 --- a/tsl/test/isolation/specs/cagg_multi_dist_ht.spec +++ /dev/null @@ -1,103 +0,0 @@ -# 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. - -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'cdrp_1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_2', host => 'localhost', database => 'cdrp_2', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_3', host => 'localhost', database => 'cdrp_3', if_not_exists => true); } -setup -{ - SELECT _timescaledb_functions.stop_background_workers(); - CREATE TABLE ts_continuous_test(time INTEGER, val INTEGER); - SELECT create_distributed_hypertable('ts_continuous_test', 'time', chunk_time_interval => 10, replication_factor => 2); - CREATE OR REPLACE FUNCTION integer_now_test() returns INT LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM ts_continuous_test $$; - CALL distributed_exec($DIST$ - CREATE OR REPLACE FUNCTION integer_now_test() returns INT LANGUAGE SQL STABLE as $$ SELECT coalesce(max(time), 0) FROM ts_continuous_test $$; - $DIST$); - SELECT set_integer_now_func('ts_continuous_test', 'integer_now_test'); - INSERT INTO ts_continuous_test SELECT i, i FROM - (SELECT generate_series(0, 29) AS i) AS i; -} - -#needed to avoid "SQL step too long" error in setup -session "SetupContinue" -step "Setup2" -{ - CREATE MATERIALIZED VIEW continuous_view_1( bkt, cnt) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), COUNT(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE MATERIALIZED VIEW continuous_view_2(bkt, maxl) - WITH ( timescaledb.continuous, timescaledb.materialized_only = true) - AS SELECT time_bucket('5', time), max(val) - FROM ts_continuous_test - GROUP BY 1 WITH NO DATA; - CREATE FUNCTION lock_mattable(schema_name TEXT, table_name TEXT) RETURNS void AS $$ - BEGIN EXECUTE format('LOCK TABLE %I.%I', schema_name, table_name); - END; $$ LANGUAGE plpgsql; -} - -# need to do multiple transactions in teardown -session "TearDownMultiTransaction" -setup { SET client_min_messages TO WARNING; } -step "TearD1" -{ - DROP FUNCTION lock_mattable(TEXT, TEXT); -} -step "TearD2" -{ - DROP TABLE ts_continuous_test CASCADE; -} - -session "I" -step "I1" { INSERT INTO ts_continuous_test SELECT 0, i*10 FROM (SELECT generate_series(0, 10) AS i) AS i; } -step "I2" { INSERT INTO ts_continuous_test SELECT 40, 1000 ; } - -session "R1" -setup { SET client_min_messages TO NOTICE; } -step "Refresh1" { CALL refresh_continuous_aggregate('continuous_view_1', NULL, 30); } - -session "R1_sel" -step "Refresh1_sel" { select * from continuous_view_1 where bkt = 0 or bkt > 30 } - -session "R2" -setup { SET client_min_messages TO NOTICE; } -step "Refresh2" { CALL refresh_continuous_aggregate('continuous_view_2', NULL, NULL); } - -session "R2_sel" -step "Refresh2_sel" { select * from continuous_view_2 where bkt = 0 or bkt > 30 order by bkt; } - -#locking the materialized table will block refresh1 -session "LM1" -step "LockMat1" { BEGIN; select lock_mattable(materialization_hypertable_schema, materialization_hypertable_name) FROM ( SELECT materialization_hypertable_schema, materialization_hypertable_name from timescaledb_information.continuous_aggregates where view_name::text like 'continuous_view_1') q ; -} -step "UnlockMat1" { ROLLBACK; } - -#update the hypertable -session "Upd" -step "U1" { update ts_continuous_test SET val = 5555 where time < 10; } -step "U2" { update ts_continuous_test SET val = 5 where time > 15 and time < 25; } - -#simulate an update to the invalidation threshold table that would lock the hypertable row -#this would block refresh that needs to get a row lock for the hypertable -session "LInv" -step "LInvRow" { BEGIN; update _timescaledb_catalog.continuous_aggs_invalidation_threshold set watermark = 20 where hypertable_id in ( select raw_hypertable_id from _timescaledb_catalog.continuous_agg where user_view_name like 'continuous_view_1' ); -} -step "UnlockInvRow" { ROLLBACK; } - - -#refresh1, refresh2 can run concurrently -permutation "Setup2" "LockMat1" "Refresh1" "Refresh2" "UnlockMat1" "TearD1" "TearD2" - -#refresh1 and refresh2 run concurrently and see the correct invalidation -#test1 - both see the same invalidation -permutation "Setup2" "Refresh1" "Refresh2" "LockMat1" "I1" "Refresh1" "Refresh2" "UnlockMat1" "Refresh1_sel" "Refresh2_sel" "TearD1" "TearD2" - -##test2 - continuous_view_2 should see results from insert but not the other one. -## Refresh2 will complete first due to LockMat1 and write the invalidation logs out. -permutation "Setup2" "Refresh1" "Refresh2" "Refresh1_sel" "Refresh2_sel" "LockMat1" "I2" "Refresh1" "Refresh2" "UnlockMat1" "Refresh1_sel" "Refresh2_sel" "TearD1" "TearD2" - -#test3 - both see the updates i.e. the invalidations -##Refresh1 and Refresh2 are blocked by LockInvRow, when that is unlocked, they should complete serially -permutation "Setup2" "Refresh1" "Refresh2" "Refresh1_sel" "Refresh2_sel" "U1" "U2" "LInvRow" "Refresh1" "Refresh2" "UnlockInvRow" "Refresh1_sel" "Refresh2_sel" "TearD1" "TearD2" diff --git a/tsl/test/isolation/specs/dist_cmd_exec.spec.in b/tsl/test/isolation/specs/dist_cmd_exec.spec.in deleted file mode 100644 index 6413204478a..00000000000 --- a/tsl/test/isolation/specs/dist_cmd_exec.spec.in +++ /dev/null @@ -1,64 +0,0 @@ -# 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. - -# -# Test dist_cmd_invoke_on_data_nodes_using_search_path() connection cache -# invalidation race -# -setup -{ - CREATE FUNCTION invalidate_data_node(node_name NAME) RETURNS BOOL LANGUAGE C STRICT - AS '@TSL_MODULE_PATHNAME@', 'ts_test_alter_data_node'; - - SET timescaledb_experimental.enable_distributed_ddl=off; - CREATE SCHEMA dist_schema; - CREATE TABLE IF NOT EXISTS dist_schema.disttable(time timestamptz NOT NULL, device int, temp float); -} -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'dn_1', if_not_exists => true); } -setup { CALL distributed_exec('CREATE SCHEMA dist_schema', transactional => false); } -setup { SELECT created FROM create_distributed_hypertable('dist_schema.disttable', 'time', 'device'); } - -teardown -{ - DROP SCHEMA dist_schema CASCADE; -} - -# locking session -session "s1" -setup -{ - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET application_name = 's1'; -} -step "s1_lock1" { SELECT debug_waitpoint_enable('dist_cmd_using_search_path_1'); } -step "s1_unlock1" { SELECT debug_waitpoint_release('dist_cmd_using_search_path_1'); } -step "s1_lock2" { SELECT debug_waitpoint_enable('dist_cmd_using_search_path_2'); } -step "s1_unlock2" { SELECT debug_waitpoint_release('dist_cmd_using_search_path_2'); } -step "s1_invalidate" { - SELECT invalidate_data_node('data_node_1'); -} - -session "s2" -setup -{ - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET application_name = 's2'; -} -step "s2_set_search_path" { - SET search_path = dist_schema; - SHOW search_path; -} - -step "s2_analyze" { ANALYZE disttable; } - -# -# Test connection cache invalidation ignore between sequential execution of -# non-transactional commands using the same connection. -# -# Invalidate connection after search_path being executed, this will force to reopen -# connection and produce an error otherwise. -# -# Issue: #4022 -# -permutation "s1_lock1" "s1_lock2" "s2_set_search_path" "s2_analyze" "s1_invalidate" "s1_unlock1" "s1_invalidate" "s1_unlock2" diff --git a/tsl/test/isolation/specs/dist_ha_chunk_drop.spec b/tsl/test/isolation/specs/dist_ha_chunk_drop.spec deleted file mode 100644 index f3b400c4507..00000000000 --- a/tsl/test/isolation/specs/dist_ha_chunk_drop.spec +++ /dev/null @@ -1,57 +0,0 @@ -# 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. - -# -# Test concurrent insert into dist hypertable after a data node marked -# as unavailable would produce 'tuple concurrently deleted` error. -# -# The problem occurs because of missing tuple level locking during scan and concurrent -# delete from chunk_data_node table afterwards, which should be treated as -# `SELECT … FOR UPDATE`. -# -setup -{ - CREATE TABLE metric1(ts TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL); -} - -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'cdha_1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_2', host => 'localhost', database => 'cdha_2', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_3', host => 'localhost', database => 'cdha_3', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_4', host => 'localhost', database => 'cdha_4', if_not_exists => true); } -setup { SELECT created FROM create_distributed_hypertable('metric1', 'ts', 'dev_id', chunk_time_interval => INTERVAL '1 hour', replication_factor => 4); } - -teardown -{ - DROP TABLE metric1; -} - -# bootstrap cluster with data -session "s1" -setup -{ - SET application_name = 's1'; -} -step "s1_init" { INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:00:00'::timestamp, '2021-08-17 00:00:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(1, 500) d; } -step "s1_set_unavailable" { SELECT alter_data_node('data_node_4', available=>false); } -step "s1_set_available" { SELECT alter_data_node('data_node_4', available=>true); } -step "s1_insert" { INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:01:00'::timestamp, '2021-08-17 00:01:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(1, 249) d; } - -# concurrent session -session "s2" -setup -{ - SET application_name = 's2'; -} -step "s2_insert" { INSERT INTO metric1(ts, val, dev_id) SELECT s.*, 3.14, d.* FROM generate_series('2021-08-17 00:01:00'::timestamp, '2021-08-17 00:01:59'::timestamp, '1 s'::interval) s CROSS JOIN generate_series(250, 499) d; } - -# locking session -session "s3" -setup -{ - SET application_name = 's3'; -} -step "s3_lock_enable" { SELECT debug_waitpoint_enable('chunk_data_node_delete'); } -step "s3_lock_release" { SELECT debug_waitpoint_release('chunk_data_node_delete'); } - -permutation "s1_init" "s1_set_unavailable" "s3_lock_enable" "s1_insert" "s2_insert" "s3_lock_release" "s1_set_available" diff --git a/tsl/test/isolation/specs/dist_restore_point.spec b/tsl/test/isolation/specs/dist_restore_point.spec deleted file mode 100644 index 8688f55d095..00000000000 --- a/tsl/test/isolation/specs/dist_restore_point.spec +++ /dev/null @@ -1,97 +0,0 @@ -# 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. - -# Test create_distributed_restore_point() concurrency cases -# -setup -{ - CREATE OR REPLACE FUNCTION waitpoint_locks(tag TEXT) RETURNS bigint AS - $$ - SELECT count(*) FROM pg_locks WHERE objid = debug_waitpoint_id(tag); - $$ LANGUAGE SQL; - - CREATE OR REPLACE FUNCTION remote_txn_locks() RETURNS bigint AS - $$ - SELECT count(*) FROM pg_locks WHERE relation = '_timescaledb_catalog.remote_txn'::regclass; - $$ LANGUAGE SQL; - - CREATE OR REPLACE FUNCTION foreign_server_locks() RETURNS bigint AS - $$ - SELECT count(*) FROM pg_locks WHERE relation = 'pg_catalog.pg_foreign_server'::regclass; - $$ LANGUAGE SQL; - - CREATE TABLE IF NOT EXISTS disttable(time timestamptz NOT NULL, device int, temp float); -} -setup { SELECT true AS delete_data_node FROM delete_data_node('data_node_4', if_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_1', host => 'localhost', database => 'cdrp_1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_2', host => 'localhost', database => 'cdrp_2', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('data_node_3', host => 'localhost', database => 'cdrp_3', if_not_exists => true); } -setup { SELECT created FROM create_distributed_hypertable('disttable', 'time', 'device', data_nodes => ARRAY['data_node_1', 'data_node_2', 'data_node_3']); } - -teardown -{ - DROP TABLE disttable; -} - -# create distributed restore point -session "s1" -setup -{ - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET application_name = 's1'; - SET client_min_messages = 'ERROR'; -} -step "s1_create_dist_rp" { SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s1_test'); } - -# concurrent remote transaction -session "s2" -setup -{ - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET application_name = 's2'; - SET client_min_messages = 'ERROR'; -} -step "s2_create_dist_rp" { SELECT restore_point > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('s2_test'); } -step "s2_insert" { INSERT INTO disttable VALUES ('2019-08-02 10:45', 0, 0.0); } -step "s2_begin" { BEGIN; } -step "s2_commit" { COMMIT; } -step "s2_create_dist_ht" { - CREATE TABLE disttable2(time timestamptz NOT NULL, device int, temp float); - SELECT created FROM create_distributed_hypertable('disttable2', 'time', 'device'); -} -step "s2_drop_dist_ht" { DROP TABLE disttable2; } -step "s2_dist_exec" { CALL distributed_exec('SELECT true;', transactional => true); } - -# locking session -session "s3" -setup -{ - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET application_name = 's3'; - SET client_min_messages = 'ERROR'; -} -step "s3_lock_enable" { SELECT debug_waitpoint_enable('create_distributed_restore_point_lock'); } -step "s3_lock_release" { SELECT debug_waitpoint_release('create_distributed_restore_point_lock'); } -step "s3_lock_count" { - SELECT waitpoint_locks('create_distributed_restore_point_lock') as cdrp_locks, - remote_txn_locks() as remote_txn_locks; -} - -# case 1: new transaction DML/commit during the create_distributed_restore_point() -permutation "s3_lock_enable" "s1_create_dist_rp" "s2_insert" "s3_lock_count" "s3_lock_release" - -# case 2: ongoing transaction DML/commit during the create_distributed_restore_point() -permutation "s2_begin" "s2_insert" "s3_lock_enable" "s1_create_dist_rp" "s3_lock_count" "s2_commit" "s3_lock_count" "s3_lock_release" - -# case 3: concurrent create_distributed_restore_point() call -permutation "s3_lock_enable" "s1_create_dist_rp" "s2_create_dist_rp" "s3_lock_count" "s3_lock_release" - -# case 4: concurrent distributed_exec() call during the the create_distributed_restore_point() -permutation "s3_lock_enable" "s1_create_dist_rp" "s2_dist_exec" "s3_lock_count" "s3_lock_release" - -# case 5: concurrent create_distributed_hypertable() during the the create_distributed_restore_point() -permutation "s3_lock_enable" "s1_create_dist_rp" "s2_create_dist_ht" "s3_lock_count" "s3_lock_release" - -# case 6: concurrent DDL/commit during the create_distributed_restore_point() -permutation "s3_lock_enable" "s1_create_dist_rp" "s2_drop_dist_ht" "s3_lock_count" "s3_lock_release" diff --git a/tsl/test/isolation/specs/dist_su_copy_chunk.spec.in b/tsl/test/isolation/specs/dist_su_copy_chunk.spec.in deleted file mode 100644 index 30125f6f84d..00000000000 --- a/tsl/test/isolation/specs/dist_su_copy_chunk.spec.in +++ /dev/null @@ -1,103 +0,0 @@ -# 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. - -# Test that when the empty chunk is created as part of a copy or move chunk, that -# its owner is a superuser and different from the original hypertable owner -# -# This change necessitated due to a security hole in logical replication in Postgres - -setup -{ - SET timescaledb_experimental.enable_distributed_ddl=off; - - CREATE OR REPLACE FUNCTION remote_exec(srv_name name[], command text) - RETURNS VOID AS '@TSL_MODULE_PATHNAME@', 'ts_remote_exec' LANGUAGE C; - - DROP ROLE IF EXISTS htowner1; - CREATE ROLE htowner1 LOGIN; - GRANT CREATE ON SCHEMA public TO htowner1; - SET ROLE htowner1; - CREATE TABLE test(time timestamp NOT NULL, device int, temp text); - RESET ROLE; - ALTER SEQUENCE _timescaledb_catalog.hypertable_id_seq RESTART; - ALTER SEQUENCE _timescaledb_catalog.chunk_id_seq RESTART; -} -setup { SELECT node_name FROM add_data_node('dn_1', host => 'localhost', database => 'dn1', if_not_exists => true); } -setup { SELECT node_name FROM add_data_node('dn_2', host => 'localhost', database => 'dn2', if_not_exists => true); } -setup { CALL distributed_exec('GRANT CREATE ON SCHEMA public TO htowner1;'); } -setup -{ - GRANT USAGE ON FOREIGN SERVER dn_1, dn_2 TO PUBLIC; - SET ROLE htowner1; - SET timescaledb_experimental.enable_distributed_ddl=on; -} -setup -{ - SELECT create_distributed_hypertable('test', 'time', 'device', 3, associated_schema_name => 'public'); - INSERT INTO test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -} - -teardown -{ - DROP TABLE test CASCADE; -} - -session "s1" -setup -{ - SET application_name = 's1'; -} -step "s1_wait1" { SELECT debug_waitpoint_enable('chunk_copy_after_empty_chunk'); } -step "s1_release1" { SELECT debug_waitpoint_release('chunk_copy_after_empty_chunk'); } - -session "s2" -setup -{ - SET application_name = 's2'; - SET ROLE htowner1; -} -step "s2_copy1" { - CALL timescaledb_experimental.move_chunk(chunk=>'public._dist_hyper_1_1_chunk', source_node=> 'dn_1', destination_node => 'dn_2') -} - -session "s3" -setup -{ - SET application_name = 's3'; -} - -# this should show 1 on "dn_2" and nothing on "dn_1" -step "s3_check1" -{ - SELECT * FROM remote_exec(ARRAY['dn_1', 'dn_2'], $DIST$ - SELECT 1 FROM pg_catalog.pg_tables WHERE schemaname = 'public' AND tablename = - '_dist_hyper_1_1_chunk' AND tableowner != 'htowner1'; $DIST$); -} - -# this should show true on "dn_2" and false on "dn_1" on first invocation -# it should show false on "dn_2" and nothing on "dn_1" after the move -step "s3_check2" -{ - SELECT * FROM remote_exec(ARRAY['dn_1', 'dn_2'], $DIST$ - SELECT usesuper FROM pg_user WHERE usename IN (SELECT tableowner FROM pg_catalog.pg_tables WHERE schemaname = - 'public' AND tablename = '_dist_hyper_1_1_chunk'); $DIST$); -} - -# this should fail on dn_2 since superuser owns the chunk object. Kinda superfluous since -# we already checked for superuser above -step "s3_check3" -{ - SET ROLE htowner1; - SELECT * FROM remote_exec(ARRAY['dn_2'], $DIST$ - CREATE INDEX ON public._dist_hyper_1_1_chunk (lower(temp)); - $DIST$); -} - -# -# Test that when the empty chunk is created as part of a copy or move chunk, that -# its owner is a superuser and different from the original hypertable owner -# -# This change necessitated due to a security hole in logical replication in Postgres -# -permutation "s1_wait1" "s2_copy1" "s3_check1" "s3_check2" "s3_check3" "s1_release1" "s3_check2" diff --git a/tsl/test/isolation/specs/remote_create_chunk.spec b/tsl/test/isolation/specs/remote_create_chunk.spec deleted file mode 100644 index ced30e20f9b..00000000000 --- a/tsl/test/isolation/specs/remote_create_chunk.spec +++ /dev/null @@ -1,103 +0,0 @@ -# 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. - -# Test concurrent remote chunk creation -# - -setup -{ - CREATE TABLE conditions (time timestamptz, device int, temp float); - SELECT create_hypertable('conditions', 'time', 'device', 2, chunk_time_interval => interval '1 day'); - - CREATE OR REPLACE FUNCTION waitpoint_count(tag TEXT) RETURNS bigint AS - $$ - SELECT count(*) - FROM pg_locks - WHERE locktype = 'advisory' - AND mode = 'ShareLock' - AND objid = debug_waitpoint_id(tag) - AND granted = false; - $$ LANGUAGE SQL; - - CREATE OR REPLACE FUNCTION root_table_lock_count() RETURNS bigint AS - $$ - SELECT count(*) AS num_locks_on_conditions_table - FROM pg_locks - WHERE locktype = 'relation' - AND relation = 'conditions'::regclass - AND mode = 'ShareUpdateExclusiveLock'; - $$ LANGUAGE SQL; -} - -teardown { - DROP TABLE conditions; -} - - -session "s1" -setup { - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET LOCAL lock_timeout = '500ms'; - SET LOCAL deadlock_timeout = '300ms'; - SET application_name = 's1'; -} - -# Try to create a chunk -step "s1_create_chunk_1" { - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); -} - -# Create a chunk that does not exist -session "s2" -setup { - SET TRANSACTION ISOLATION LEVEL READ COMMITTED; - SET LOCAL lock_timeout = '500ms'; - SET LOCAL deadlock_timeout = '300ms'; - SET application_name = 's1'; -} - -step "s2_create_chunk_1" { - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[-9223372036854775808, 1073741823])); -} - -step "s2_create_chunk_2" { - SELECT slices, created FROM _timescaledb_functions.create_chunk('conditions', jsonb_build_object('time', ARRAY[1514764800000000, 1514851200000000], 'device', ARRAY[1073741823, 9223372036854775807])); -} - -session "s3" -setup { - SET application_name = 's3'; -} - -step "s3_conditions_locks" { - SELECT root_table_lock_count() AS table_lock, - waitpoint_count('find_or_create_chunk_start') AS at_start, - waitpoint_count('find_or_create_chunk_created') AS at_created, - waitpoint_count('find_or_create_chunk_found') AS at_found; -} - -session "s4" -step "s4_wait_start" { SELECT debug_waitpoint_enable('find_or_create_chunk_start'); } -step "s4_wait_created" { SELECT debug_waitpoint_enable('find_or_create_chunk_created'); } -step "s4_wait_found" { SELECT debug_waitpoint_enable('find_or_create_chunk_found'); } -step "s4_release_start" { SELECT debug_waitpoint_release('find_or_create_chunk_start'); } -step "s4_release_created" { SELECT debug_waitpoint_release('find_or_create_chunk_created'); } -step "s4_release_found" { SELECT debug_waitpoint_release('find_or_create_chunk_found'); } - -# s1 and s2 will try create the same chunk and both take the lock on -# the root table. However, s2 will find the chunk created by s1 after -# s1 releases the root lock and then s2 will also release the root -# lock before transaction end. -permutation "s4_wait_created" "s4_wait_found" "s1_create_chunk_1" "s2_create_chunk_1" "s3_conditions_locks" "s4_release_created" "s3_conditions_locks" "s4_release_found" - -# s1 and s2 will create different chunks and both will try to lock the -# root table. They will each create their own unique chunks, so s2 -# won't block on the "found" wait point. -permutation "s4_wait_created" "s4_wait_found" "s1_create_chunk_1" "s2_create_chunk_2" "s3_conditions_locks" "s4_release_created" "s3_conditions_locks" "s4_release_found" - -# s1 and s2 runs concurrently and both try to create the same -# chunk. However, s1 completes its transaction before s2 looks up the -# chunk. Therefore s2 will find the new chunk and need not take the -# lock on the root table. -permutation "s4_wait_created" "s1_create_chunk_1" "s4_wait_start" "s2_create_chunk_1" "s3_conditions_locks" "s4_release_created" "s3_conditions_locks" "s4_release_start" "s3_conditions_locks" diff --git a/tsl/test/shared/sql/.gitignore b/tsl/test/shared/sql/.gitignore index 1e6053ee040..920210fc804 100644 --- a/tsl/test/shared/sql/.gitignore +++ b/tsl/test/shared/sql/.gitignore @@ -1,9 +1,5 @@ /continuous_aggs_compression-*.sql /constify_now-*.sql -/dist_distinct-*.sql -/dist_fetcher_type-*.sql -/dist_remote_error-*.sql -/dist_remote_error.text /gapfill-*.sql /generated_columns-*.sql /ordered_append-*.sql diff --git a/tsl/test/shared/sql/include/dist_distinct_run.sql b/tsl/test/shared/sql/include/dist_distinct_run.sql deleted file mode 100644 index cb3b64ed902..00000000000 --- a/tsl/test/shared/sql/include/dist_distinct_run.sql +++ /dev/null @@ -1,143 +0,0 @@ --- 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. - -\echo '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%' -\echo '%%% RUNNING TESTS on table:' :TABLE_NAME -\echo '%%% PREFIX:' :PREFIX -\echo '%%% ORDER_BY_1:' :ORDER_BY_1 -\echo '%%% ORDER_BY_1_2:' :ORDER_BY_1_2 -\echo '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%' - --- Test SkipScan with SELECT DISTINCT in multi-node environment --- Ensure that a Unique plan gets chosen on the access node -SET enable_hashagg TO false; -\qecho Unique plan on access node for SELECT DISTINCT -:PREFIX -SELECT DISTINCT device_id -FROM :TABLE_NAME -:ORDER_BY_1 -LIMIT 10; -RESET enable_hashagg; - -SET timescaledb.enable_per_data_node_queries = true; --- SELECT DISTINCT on expressions won't be pushed down -\qecho SELECT DISTINCT on expressions is not pushed down -:PREFIX -SELECT DISTINCT device_id*v1 -FROM :TABLE_NAME -:ORDER_BY_1 -LIMIT 10; - -SET timescaledb.enable_remote_explain = ON; --- SELECT DISTINCT on column with index should use SkipScan -\qecho SELECT DISTINCT on column with index uses SkipScan -:PREFIX -SELECT DISTINCT device_id -FROM :TABLE_NAME -:ORDER_BY_1 -LIMIT 10; - --- SELECT DISTINCT with constants and NULLs in targetlist should use SkipScan -\qecho SELECT DISTINCT with constants and NULLs in targetlist uses SkipScan -:PREFIX -SELECT DISTINCT device_id, NULL, 'const1' -FROM :TABLE_NAME -:ORDER_BY_1 -LIMIT 10; - --- SELECT DISTINCT with a mix of constants and columns should send only --- the columns to the remote side. However SkipScan won't be used because --- right now only single column is supported in SkipScans -\qecho SELECT DISTINCT only sends columns to the data nodes -:PREFIX -SELECT DISTINCT device_id, time, NULL, 'const1' -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10; - --- SELECT DISTINCT will be pushed down in the attribute attno order. This --- is ok because "DISTINCT SELECT col1, col2" returns the same values --- (subject to ORDER BY clauses) as "DISTINCE SELECT col2, col1" -\qecho SELECT DISTINCE is pushed down in attribute attno order -:PREFIX -SELECT DISTINCT device_id, time -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10; - --- SELECT DISTINCT ON on multiple columns will be pushed to the remote side. --- However SkipScan won't be used since only one column is supported -\qecho SELECT DISTINCT ON multiple columns is pushed to data nodes -:PREFIX -SELECT DISTINCT ON (device_id, time) device_id, time -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10; - --- Another variation with SELECT DISTINCT -\qecho SELECT DISTINCT within a sub-select -:PREFIX -SELECT device_id, time, 'const1' FROM (SELECT DISTINCT ON (device_id) device_id, time -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10) a; - --- Ensure that SELECT DISTINCT pushdown happens even with below disabled -SET timescaledb.enable_per_data_node_queries = false; -\qecho SELECT DISTINCT works with enable_per_data_node_queries disabled -:PREFIX -SELECT DISTINCT device_id -FROM :TABLE_NAME -:ORDER_BY_1 -LIMIT 10; - -SET timescaledb.enable_per_data_node_queries = true; -SET timescaledb.enable_remote_explain = OFF; - --- SELECT DISTINCT should not have duplicate columns -\qecho SELECT DISTINCT should not have duplicate columns -:PREFIX -SELECT DISTINCT device_id, device_id -FROM :TABLE_NAME -:ORDER_BY_1; - --- SELECT DISTINCT handles whole row correctly -\qecho SELECT DISTINCT handles whole row correctly -:PREFIX -SELECT DISTINCT * -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10; - --- SELECT DISTINCT ON handles whole row correctly -\qecho SELECT DISTINCT ON (expr) handles whole row correctly -:PREFIX -SELECT DISTINCT ON (device_id) * -FROM :TABLE_NAME -ORDER BY device_id, time -LIMIT 10; - --- SELECT DISTINCT RECORD works correctly -\qecho SELECT DISTINCT RECORD works correctly -SET enable_hashagg TO false; -:PREFIX -SELECT DISTINCT :TABLE_NAME r -FROM :TABLE_NAME -ORDER BY r -LIMIT 10; -RESET enable_hashagg; - --- SELECT DISTINCT function is not pushed down -\qecho SELECT DISTINCT FUNCTION_EXPR not pushed down currently -:PREFIX -SELECT DISTINCT time_bucket('1h',time) col1 -FROM :TABLE_NAME -ORDER BY col1 -LIMIT 10; - --- SELECT DISTINCT without any var references is handled correctly -\qecho SELECT DISTINCT without any var references is handled correctly -:PREFIX -SELECT DISTINCT 1, 'constx' -FROM :TABLE_NAME; diff --git a/tsl/test/shared/sql/include/dist_gapfill_query.sql b/tsl/test/shared/sql/include/dist_gapfill_query.sql deleted file mode 100644 index 7c10899d019..00000000000 --- a/tsl/test/shared/sql/include/dist_gapfill_query.sql +++ /dev/null @@ -1,29 +0,0 @@ --- 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. - -SELECT time_bucket_gapfill('3 hours', time, start:='2017-01-01 06:00', finish:='2017-01-02 18:00'), - first(value, time), - avg(value) -FROM :CONDITIONS -GROUP BY 1; - -SELECT time_bucket_gapfill('3 hours', time, start:='2017-01-01 06:00', finish:='2017-01-01 18:00'), - device, - first(value, time), - avg(value) -FROM :CONDITIONS -GROUP BY 1,2; - -SELECT time_bucket_gapfill('3 hours', time, start:='2017-01-01 06:00', finish:='2017-01-01 18:00'), - device, - first(value, time), - avg(value) -FROM :CONDITIONS -GROUP BY 2,1; - -SELECT - time_bucket_gapfill('3 hours', time, start:='2017-01-01 06:00', finish:='2017-01-01 18:00'), - lag(min(time)) OVER () -FROM :CONDITIONS -GROUP BY 1; diff --git a/tsl/test/sql/.gitignore b/tsl/test/sql/.gitignore index 3faa1a22185..bc9195c50b8 100644 --- a/tsl/test/sql/.gitignore +++ b/tsl/test/sql/.gitignore @@ -16,23 +16,9 @@ /continuous_aggs-*.sql /continuous_aggs_deprecated-*.sql /deparse-*.sql -/dist_grant-*.sql -/dist_query-*.sql -/dist_hypertable-*.sql -/dist_partial_agg-*.sql -/dist_ref_table_join-*.sql -/dist_ref_table_join-*.sql -/dist_remote_error-*.sql -/dist_remote_error.text -/dist_views-*.sql -/dist_compression-*.sql -/dist_move_chunk-*.sql -/dist_util-*.sql -/hypertable_distributed-*.sql /jit-*.sql /modify_exclusion-*.sql /plan_skip_scan-*.sql -/remote-copy-*sv /transparent_decompression-*.sql /transparent_decompression_join_index-*.sql /transparent_decompression_ordered_index-*.sql diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index db32cfbceb3..dbd949efb2f 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -34,10 +34,6 @@ set(TEST_FILES size_utils_tsl.sql vectorized_aggregation.sql) -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list(APPEND TEST_FILES dist_param.sql) -endif() - if(USE_TELEMETRY) list(APPEND TEST_FILES bgw_telemetry.sql) endif() @@ -88,38 +84,6 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) recompress_chunk_segmentwise.sql feature_flags.sql) - if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list( - APPEND - TEST_FILES - cagg_bgw_dist_ht.sql - cagg_ddl_dist_ht.sql - cagg_migrate_dist_ht.sql - cagg_on_cagg_dist_ht.sql - cagg_on_cagg_joins_dist_ht.sql - data_fetcher.sql - data_node_bootstrap.sql - data_node.sql - debug_notice.sql - dist_api_calls.sql - dist_commands.sql - dist_copy_available_dns.sql - dist_copy_format_long.sql - dist_copy_long.sql - dist_ddl.sql - dist_cagg.sql - dist_policy.sql - dist_triggers.sql - dist_backup.sql - remote_connection_cache.sql - remote_connection.sql - remote_copy.sql - remote_stmt_params.sql - remote_txn_id.sql - remote_txn_resolve.sql - remote_txn.sql) - endif() - endif(CMAKE_BUILD_TYPE MATCHES Debug) if((${PG_VERSION_MAJOR} GREATER_EQUAL "14")) @@ -135,8 +99,6 @@ if((${PG_VERSION_MAJOR} GREATER_EQUAL "15")) endif() set(SOLO_TESTS - # dist_hypertable needs a lot of memory when the Sanitizer is active - dist_hypertable-${PG_VERSION_MAJOR} # This interferes with other tests since it reloads the config to increase # log level. bgw_scheduler_control @@ -151,7 +113,6 @@ set(SOLO_TESTS cagg_bgw cagg_ddl-${PG_VERSION_MAJOR} cagg_dump - dist_util-${PG_VERSION_MAJOR} move remote_connection_cache remote_copy @@ -159,17 +120,6 @@ set(SOLO_TESTS remote_txn_resolve reorder telemetry_stats-${PG_VERSION_MAJOR}) -# In PG versions 15.0 to 15.2, dist_move_chunk can cause a deadlock when run in -# parallel with other tests as mentioned in #4972. -if(ENABLE_MULTINODE_TESTS - AND ${PG_VERSION_MAJOR} EQUAL "15" - AND ${PG_VERSION_MINOR} LESS "3") - list(APPEND SOLO_TESTS dist_move_chunk-${PG_VERSION_MAJOR}) -endif() - -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list(APPEND SOLO_TESTS cagg_bgw_dist_ht data_fetcher) -endif() set(TEST_TEMPLATES bgw_custom.sql.in @@ -204,27 +154,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) if(USE_TELEMETRY) list(APPEND TEST_TEMPLATES telemetry_stats.sql.in) endif() - if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list( - APPEND - TEST_TEMPLATES - cagg_invalidation_dist_ht.sql.in - dist_hypertable.sql.in - dist_grant.sql.in - dist_ref_table_join.sql.in - dist_remote_error.sql.in - dist_partial_agg.sql.in - dist_query.sql.in - dist_compression.sql.in - dist_move_chunk.sql.in - dist_util.sql.in) - endif() endif(CMAKE_BUILD_TYPE MATCHES Debug) -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list(APPEND TEST_TEMPLATES dist_views.sql.in) -endif() - # Check if PostgreSQL was compiled with JIT support set(PG_CONFIG_H "${PG_INCLUDEDIR}/pg_config.h") if(EXISTS ${PG_CONFIG_H}) diff --git a/tsl/test/sql/cagg_bgw_dist_ht.sql b/tsl/test/sql/cagg_bgw_dist_ht.sql deleted file mode 100644 index 9253e30dca0..00000000000 --- a/tsl/test/sql/cagg_bgw_dist_ht.sql +++ /dev/null @@ -1,34 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\ir include/remote_exec.sql - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; - -\set IS_DISTRIBUTED TRUE - -\ir include/cagg_bgw_common.sql - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/cagg_ddl_dist_ht.sql b/tsl/test/sql/cagg_ddl_dist_ht.sql deleted file mode 100644 index ec6dbcf875e..00000000000 --- a/tsl/test/sql/cagg_ddl_dist_ht.sql +++ /dev/null @@ -1,33 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\ir include/remote_exec.sql - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\set IS_DISTRIBUTED TRUE - -\ir include/cagg_ddl_common.sql - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/cagg_invalidation_dist_ht.sql.in b/tsl/test/sql/cagg_invalidation_dist_ht.sql.in deleted file mode 100644 index 5d4b83d9122..00000000000 --- a/tsl/test/sql/cagg_invalidation_dist_ht.sql.in +++ /dev/null @@ -1,33 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\ir include/remote_exec.sql - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER, :ROLE_DEFAULT_PERM_USER_2; - -\set IS_DISTRIBUTED TRUE - -\ir include/cagg_invalidation_common.sql - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/cagg_migrate_dist_ht.sql b/tsl/test/sql/cagg_migrate_dist_ht.sql deleted file mode 100644 index 5cd175b895e..00000000000 --- a/tsl/test/sql/cagg_migrate_dist_ht.sql +++ /dev/null @@ -1,51 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\ir include/remote_exec.sql - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - -\set IS_DISTRIBUTED TRUE - --- ######################################################## --- ## INTEGER data type tests --- ######################################################## -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\ir include/cagg_migrate_common.sql - --- ######################################################## --- ## TIMESTAMP data type tests --- ######################################################## -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMP -\ir include/cagg_migrate_common.sql - --- ######################################################## --- ## TIMESTAMPTZ data type tests --- ######################################################## -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\ir include/cagg_migrate_common.sql - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/cagg_on_cagg_dist_ht.sql b/tsl/test/sql/cagg_on_cagg_dist_ht.sql deleted file mode 100644 index e22fb4c4dc5..00000000000 --- a/tsl/test/sql/cagg_on_cagg_dist_ht.sql +++ /dev/null @@ -1,348 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set INTERVAL_TEST FALSE - -\ir include/remote_exec.sql - -SELECT (add_data_node (name, host => 'localhost', DATABASE => name)).* -FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v (name); - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- PG15 requires this explicit GRANT on schema public -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; - --- Global test variables -\set IS_DISTRIBUTED TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE -\set IS_JOIN FALSE - --- ######################################################## --- ## INTEGER data type tests --- ######################################################## - --- Current test variables -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\set INTERVAL_TEST FALSE -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 - --- --- Run common tests for INTEGER --- -\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set 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 - --- cleanup -DROP TABLE conditions; - --- ######################################################## --- ## 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 timezone TO 'UTC'; - --- --- Run common tests for TIMESTAMP --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- --- Validation test for variable bucket on top of fixed bucket --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- ######################################################## --- ## TIMESTAMPTZ data type tests --- ######################################################## - --- Current test variables -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly - -SET timezone TO 'UTC'; - --- --- Run common tests for TIMESTAMPTZ --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- --- Validation test for variable bucket on top of fixed bucket --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validations using time bucket with timezone (ref issue #5126) --- -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_5m -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_1h -\set BUCKET_TZNAME_1ST 'US/Pacific' -\set BUCKET_TZNAME_2TH 'US/Pacific' -\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'16 minutes\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Variable bucket size with the same timezones --- -\set BUCKET_TZNAME_1ST 'UTC' -\set BUCKET_TZNAME_2TH 'UTC' -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - ---#Bugfix 5734 #1 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 month\'' -\ir include/cagg_on_cagg_validations.sql -\set INTERVAL_TEST FALSE - --- --- 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 - ---#Bugfix 5734 #2 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 month\'' -\ir include/cagg_on_cagg_validations.sql -\set INTERVAL_TEST FALSE - --- --- 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 - ---#Bugfix 5734 #3 -\set INTERVAL_TEST TRUE -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 month\'' -\ir include/cagg_on_cagg_validations.sql -\set INTERVAL_TEST FALSE - --- --- 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 -\set INTERVAL_TEST FALSE - --- bug report 5231 -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 month\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\ir include/cagg_on_cagg_validations.sql - --- bug report 5277 -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE - --- epoch plus cast to int would compute a bucket width of 0 for parent -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 ms\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'9344 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'74752 ms\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'74752 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'598016 ms\'' -\ir include/cagg_on_cagg_validations.sql - --- test microseconds - should pass -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 usec\'' -\ir include/cagg_on_cagg_validations.sql - --- test microseconds - SHOULD FAIL -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1160 usec\'' -\ir include/cagg_on_cagg_validations.sql - --- Cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/cagg_on_cagg_joins_dist_ht.sql b/tsl/test/sql/cagg_on_cagg_joins_dist_ht.sql deleted file mode 100644 index 694e02e832c..00000000000 --- a/tsl/test/sql/cagg_on_cagg_joins_dist_ht.sql +++ /dev/null @@ -1,322 +0,0 @@ --- 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 up a distributed environment ------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set INTERVAL_TEST FALSE - -\ir include/remote_exec.sql - -SELECT (add_data_node (name, host => 'localhost', DATABASE => name)).* -FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v (name); - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- PG15 requires this explicit GRANT on schema public -GRANT CREATE ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; - --- Global test variables -\set IS_DISTRIBUTED TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE -\set IS_JOIN TRUE - --- ######################################################## --- ## INTEGER data type tests --- ######################################################## - --- Current test variables -\set IS_TIME_DIMENSION FALSE -\set TIME_DIMENSION_DATATYPE INTEGER -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_1 -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_5 -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_10 - --- --- Run common tests for INTEGER --- -\set BUCKET_WIDTH_1ST 'INTEGER \'1\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set BUCKET_WIDTH_3TH 'INTEGER \'10\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'5\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTEGER \'2\'' -\set BUCKET_WIDTH_2TH 'INTEGER \'2\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set 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 - --- cleanup -DROP TABLE conditions; - --- ######################################################## --- ## 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 timezone TO 'UTC'; - --- --- Run common tests for TIMESTAMP --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- --- Validation test for variable bucket on top of fixed bucket --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- ######################################################## --- ## TIMESTAMPTZ data type tests --- ######################################################## - --- Current test variables -\set IS_TIME_DIMENSION TRUE -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_hourly -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_daily -\set CAGG_NAME_3TH_LEVEL conditions_summary_3_weekly - -SET timezone TO 'UTC'; - --- --- Run common tests for TIMESTAMPTZ --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_3TH 'INTERVAL \'1 week\'' - --- Different order of time dimension in raw ht -\set IS_DEFAULT_COLUMN_ORDER FALSE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- Default tests -\set IS_DEFAULT_COLUMN_ORDER TRUE -\ir include/cagg_on_cagg_setup.sql -\ir include/cagg_on_cagg_common.sql - --- --- Validation test for variable bucket on top of fixed bucket --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'60 days\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because is not allowed variable-size bucket on top of fixed-size bucket' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for non-multiple bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 hours\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for equal bucket sizes --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 hour\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE 'SHOULD WORK because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validation test for bucket size less than source --- -\set BUCKET_WIDTH_1ST 'INTERVAL \'2 hours\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because new bucket should be greater than previous' -\ir include/cagg_on_cagg_validations.sql - --- --- Validations using time bucket with timezone (ref issue #5126) --- -\set TIME_DIMENSION_DATATYPE TIMESTAMPTZ -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE -\set CAGG_NAME_1ST_LEVEL conditions_summary_1_5m -\set CAGG_NAME_2TH_LEVEL conditions_summary_2_1h -\set BUCKET_TZNAME_1ST 'US/Pacific' -\set BUCKET_TZNAME_2TH 'US/Pacific' -\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 hour\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'5 minutes\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'16 minutes\'' -\set WARNING_MESSAGE '-- SHOULD ERROR because non-multiple bucket sizes' -\ir include/cagg_on_cagg_validations.sql - --- --- Variable bucket size with the same timezones --- -\set BUCKET_TZNAME_1ST 'UTC' -\set BUCKET_TZNAME_2TH 'UTC' -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - --- --- Variable bucket size with different timezones --- -\set BUCKET_TZNAME_1ST 'US/Pacific' -\set BUCKET_TZNAME_2TH 'UTC' -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - --- --- TZ bucket on top of non-TZ bucket --- -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH TRUE -\set BUCKET_TZNAME_2TH 'UTC' -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - --- --- non-TZ bucket on top of TZ bucket --- -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST TRUE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE -\set BUCKET_TZNAME_1ST 'UTC' -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\set WARNING_MESSAGE '-- SHOULD WORK' -\ir include/cagg_on_cagg_validations.sql - --- bug report 5231 -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 day\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'3 month\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 month\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 year\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'1 week\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1 month\'' -\ir include/cagg_on_cagg_validations.sql - --- bug report 5277 -\set IS_TIME_DIMENSION_WITH_TIMEZONE_1ST FALSE -\set IS_TIME_DIMENSION_WITH_TIMEZONE_2TH FALSE - --- epoch plus cast to int would compute a bucket width of 0 for parent -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 ms\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'9344 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'74752 ms\'' -\ir include/cagg_on_cagg_validations.sql - -\set BUCKET_WIDTH_1ST 'INTERVAL \'74752 ms\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'598016 ms\'' -\ir include/cagg_on_cagg_validations.sql - --- test microseconds - should pass -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1168 usec\'' -\ir include/cagg_on_cagg_validations.sql - --- test microseconds - SHOULD FAIL -\set BUCKET_WIDTH_1ST 'INTERVAL \'146 usec\'' -\set BUCKET_WIDTH_2TH 'INTERVAL \'1160 usec\'' -\ir include/cagg_on_cagg_validations.sql - --- Cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/data_fetcher.sql b/tsl/test/sql/data_fetcher.sql deleted file mode 100644 index 3d66e4c245b..00000000000 --- a/tsl/test/sql/data_fetcher.sql +++ /dev/null @@ -1,92 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\set TEST_BASE_NAME data_fetcher -SELECT format('include/%s_run.sql', :'TEST_BASE_NAME') as "TEST_QUERY_NAME", - format('%s/results/%s_results_cursor.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_CURSOR", - format('%s/results/%s_results_copy.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_COPY", - format('%s/results/%s_results_prepared.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_PREPARED" -\gset - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); - -SELECT setseed(1); -INSERT INTO disttable -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random() * 10 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-02'::timestamptz, '1 second') as t; - --- This table contains the content for precisely one batch of the copy fetcher. The fetch_size --- will be set to 100 below and this table contains 99 tuples and the last element on the first --- copy batch is the file trailer (#5323). -CREATE table one_batch(ts timestamptz NOT NULL, sensor_id int NOT NULL, value float NOT NULL); -SELECT create_distributed_hypertable('one_batch', 'ts'); -INSERT INTO one_batch SELECT '2023-01-01'::timestamptz AS time, sensor_id, random() AS value FROM generate_series(1, 99, 1) AS g1(sensor_id) ORDER BY time; - --- Same but for the DEFAULT_FDW_FETCH_SIZE (10000) -CREATE table one_batch_default(ts timestamptz NOT NULL, sensor_id int NOT NULL, value float NOT NULL); -SELECT create_distributed_hypertable('one_batch_default', 'ts'); -INSERT INTO one_batch_default SELECT '2023-01-01'::timestamptz AS time, sensor_id, random() AS value FROM generate_series(1, 9999, 1) AS g1(sensor_id) ORDER BY time; - -SET client_min_messages TO error; - --- Set a smaller fetch size to ensure that the result is split into --- mutliple batches. -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '100'); - --- run the queries using COPY fetcher -SET timescaledb.remote_data_fetcher = 'copy'; -\set ON_ERROR_STOP 0 -\o :TEST_RESULTS_COPY -\ir :TEST_QUERY_NAME -\o -\set ON_ERROR_STOP 1 - --- run queries using cursor fetcher -SET timescaledb.remote_data_fetcher = 'cursor'; -\o :TEST_RESULTS_CURSOR -\ir :TEST_QUERY_NAME -\o --- compare results -SELECT format('\! diff %s %s', :'TEST_RESULTS_CURSOR', :'TEST_RESULTS_COPY') as "DIFF_CMD" -\gset -:DIFF_CMD - --- run queries using prepares statement fetcher -SET timescaledb.remote_data_fetcher = 'prepared'; -\o :TEST_RESULTS_PREPARED -\ir :TEST_QUERY_NAME -\o --- compare results -SELECT format('\! diff %s %s', :'TEST_RESULTS_CURSOR', :'TEST_RESULTS_PREPARED') as "DIFF_CMD" -\gset -:DIFF_CMD - --- Test custom FDW settings. Instead of the tests above, we are not interersted --- in comparing the results of the fetchers. In the following tests we are --- interested in the actual outputs (e.g., costs). It's enough to only test them --- with one type of fetcher, because it doesn't influence the costs. -ANALYZE one_batch; - -SET timescaledb.remote_data_fetcher = 'copy'; -\ir include/data_fetcher_fdw_settings.sql - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - diff --git a/tsl/test/sql/data_node.sql b/tsl/test/sql/data_node.sql deleted file mode 100644 index 5ba782d540b..00000000000 --- a/tsl/test/sql/data_node.sql +++ /dev/null @@ -1,1010 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 -\set DN_DBNAME_4 :TEST_DBNAME _4 -\set DN_DBNAME_5 :TEST_DBNAME _5 -\set DN_DBNAME_6 :TEST_DBNAME _6 - --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; - --- Add data nodes using TimescaleDB data_node management API. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', 'localhost', database => :'DN_DBNAME_2'); -\set ON_ERROR_STOP 0 --- Add again -SELECT * FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); --- No host provided -SELECT * FROM add_data_node('data_node_99'); -SELECT * FROM add_data_node(NULL); --- Add NULL data_node -SELECT * FROM add_data_node(NULL, host => 'localhost'); -SELECT * FROM add_data_node(NULL, NULL); - --- Test invalid port numbers -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => 65536, - database => :'DN_DBNAME_3'); -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => 0, - database => :'DN_DBNAME_3'); -SELECT * FROM add_data_node('data_node_3', 'localhost', - port => -1, - database => :'DN_DBNAME_3'); - -SELECT inet_server_port() as PGPORT \gset - --- Adding a data node via ADD SERVER is blocked -CREATE SERVER data_node_4 FOREIGN DATA WRAPPER timescaledb_fdw -OPTIONS (host 'localhost', port ':PGPORT', dbname :'DN_DBNAME_4'); --- Dropping a data node via DROP SERVER is also blocked -DROP SERVER data_node_1, data_node_2; -\set ON_ERROR_STOP 1 - --- Should not generate error with if_not_exists option -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2', - if_not_exists => true); - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); - - --- Altering the host, dbname, and port should work via ALTER SERVER -BEGIN; -ALTER SERVER data_node_3 OPTIONS (SET host 'data_node_3', SET dbname 'new_db_name', SET port '9999'); -SELECT srvname, srvoptions FROM pg_foreign_server WHERE srvname = 'data_node_3'; --- Altering the name should work -ALTER SERVER data_node_3 RENAME TO data_node_4; -SELECT srvname FROM pg_foreign_server WHERE srvname = 'data_node_4'; --- Revert name and options -ROLLBACK; - -\set ON_ERROR_STOP 0 --- Should not be possible to set a version: -ALTER SERVER data_node_3 VERSION '2'; --- Should not be possible to set "available" -ALTER SERVER data_node_3 OPTIONS (SET available 'true'); -\set ON_ERROR_STOP 1 - --- Make sure changing server owner is allowed -ALTER SERVER data_node_1 OWNER TO CURRENT_USER; - --- List foreign data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -SELECT * FROM delete_data_node('data_node_3'); - --- List data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -\set ON_ERROR_STOP 0 --- Deleting a non-existing data node generates error -SELECT * FROM delete_data_node('data_node_3'); -\set ON_ERROR_STOP 1 - --- Deleting non-existing data node with "if_exists" set does not generate error -SELECT * FROM delete_data_node('data_node_3', if_exists => true); - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -SELECT * FROM delete_data_node('data_node_1'); -SELECT * FROM delete_data_node('data_node_2'); - --- No data nodes left -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; -SELECT * FROM hypertable_partitions; - --- Cleanup databases -RESET ROLE; -SET client_min_messages TO ERROR; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -SET client_min_messages TO INFO; - -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Create a distributed hypertable where no nodes can be selected --- because there are no data nodes with the right permissions. -CREATE TABLE disttable(time timestamptz, device int, temp float); -\set ON_ERROR_STOP 0 -\set VERBOSITY default -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); -\set VERBOSITY terse -\set ON_ERROR_STOP 1 - -RESET ROLE; - --- Allow ROLE_1 to create distributed tables on these data nodes. --- We'll test that data_node_3 is properly filtered when ROLE_1 --- creates a distributed hypertable without explicitly specifying --- data_node_2. -GRANT USAGE - ON FOREIGN SERVER data_node_1, data_node_2 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; - -SELECT node_name - FROM timescaledb_information.data_nodes -ORDER BY node_name; - -SELECT object_name, object_type, ARRAY_AGG(privilege_type) -FROM information_schema.role_usage_grants -WHERE object_schema NOT IN ('information_schema','pg_catalog') - AND object_type LIKE 'FOREIGN%' -GROUP BY object_schema, object_name, object_type -ORDER BY object_name, object_type; - -SET ROLE :ROLE_1; - --- Test that all data nodes are added to a hypertable and that the --- slices in the device dimension equals the number of data nodes. -BEGIN; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); - -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE column_name = 'device'; - --- Dimension partitions should be created -SELECT * FROM hypertable_partitions; - --- All data nodes with USAGE should be added. -SELECT hdn.node_name -FROM _timescaledb_catalog.hypertable_data_node hdn, _timescaledb_catalog.hypertable h -WHERE h.table_name = 'disttable' AND hdn.hypertable_id = h.id; - -ROLLBACK; - --- There should be an ERROR if we explicitly try to use a data node we --- don't have permission to use. -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', - data_nodes => '{ data_node_1, data_node_2, data_node_3 }'); -\set ON_ERROR_STOP 1 - -RESET ROLE; --- Now let ROLE_1 use data_node_3 -GRANT USAGE - ON FOREIGN SERVER data_node_3 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Now specify less slices than there are data nodes to generate a --- warning -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 2); - --- All data nodes should be added. -SELECT hdn.node_name -FROM _timescaledb_catalog.hypertable_data_node hdn, _timescaledb_catalog.hypertable h -WHERE h.table_name = 'disttable' AND hdn.hypertable_id = h.id; - --- Ensure that replication factor allows to distinguish data node hypertables from regular hypertables -SELECT replication_factor FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable'; -SELECT * FROM test.remote_exec(NULL, $$ SELECT replication_factor -FROM _timescaledb_catalog.hypertable WHERE table_name = 'disttable'; $$); - --- Create one chunk -INSERT INTO disttable VALUES ('2019-02-02 10:45', 1, 23.4); - --- Chunk mapping created -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -DROP TABLE disttable; - --- data node mappings should be cleaned up -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; -SELECT * FROM hypertable_partitions; - --- Now create tables as cluster user -CREATE TABLE disttable(time timestamptz, device int, temp float); - -\set ON_ERROR_STOP 0 --- Attach data node should fail when called on a non-hypertable -SELECT * FROM attach_data_node('data_node_1', 'disttable'); - --- Test some bad create_hypertable() parameter values for distributed hypertables --- Bad replication factor -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 0, data_nodes => '{ "data_node_2", "data_node_4" }'); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 32768); -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => -1); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => -1); - --- Non-existing data node -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 2, data_nodes => '{ "data_node_4" }'); -\set ON_ERROR_STOP 1 - --- Use a subset of data nodes and a replication factor of two so that --- each chunk is associated with more than one data node. Set --- number_partitions lower than number of servers to raise a warning -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', number_partitions => 1, replication_factor => 2, data_nodes => '{ "data_node_2", "data_node_3" }'); - --- Create some chunks -INSERT INTO disttable VALUES - ('2019-02-02 10:45', 1, 23.4), - ('2019-05-23 10:45', 4, 14.9), - ('2019-07-23 10:45', 8, 7.6); - -SELECT * FROM test.show_subtables('disttable'); -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; - --- Dropping a chunk should also clean up data node mappings -SELECT * FROM drop_chunks('disttable', older_than => '2019-05-22 17:18'::timestamptz); - -SELECT * FROM test.show_subtables('disttable'); -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - -SELECT table_name, node_name -FROM _timescaledb_catalog.chunk c, -_timescaledb_catalog.chunk_data_node cdn -WHERE c.id = cdn.chunk_id; - --- Setting the same data node should do nothing and return false -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_3'); - --- Should update the default data node and return true -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_2'); - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - --- Reset the default data node -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_3'); - -\set ON_ERROR_STOP 0 --- Will fail because data_node_2 contains chunks -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_2'); --- non-existing chunk -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('x_chunk', 'data_node_3'); --- non-existing data node -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_0000'); --- data node exists but does not store the chunk -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node('_timescaledb_internal._dist_hyper_3_3_chunk', 'data_node_1'); --- NULL try -SELECT * FROM _timescaledb_functions.set_chunk_default_data_node(NULL, 'data_node_3'); -\set ON_ERROR_STOP 1 - --- Deleting a data node removes the "foreign" chunk table(s) that --- reference that data node as "primary" and should also remove the --- hypertable_data_node and chunk_data_node mappings for that data --- node. In the future we might want to fallback to a replica data --- node for those chunks that have multiple data nodes so that the --- chunk is not removed unnecessarily. We use force => true b/c --- data_node_2 contains chunks. Dimension partitions should also be --- updated to reflect the loss of the data node. -SELECT * FROM hypertable_partitions; -SELECT * FROM delete_data_node('data_node_2', force => true); -SELECT * FROM hypertable_partitions; - -SELECT * FROM test.show_subtables('disttable'); -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; - -\set ON_ERROR_STOP 0 --- can't delete b/c it's last data replica -SELECT * FROM delete_data_node('data_node_3', force => true); -\set ON_ERROR_STOP 1 - --- Removing all data allows us to delete the data node by force, but --- with WARNING that new data will be under-replicated -TRUNCATE disttable; -SELECT * FROM delete_data_node('data_node_3', force => true); - -SELECT * FROM test.show_subtables('disttable'); -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - --- Attach data node should now succeed -SET client_min_messages TO NOTICE; -SELECT * FROM attach_data_node('data_node_1', 'disttable'); - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; - -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1'); - --- Ensure timeout returned by argument -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '0s'); -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '3s'); -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_1', interval '1 day'); - --- Create data node referencing postgres_fdw -RESET ROLE; -CREATE EXTENSION postgres_fdw; -CREATE SERVER pg_server_1 FOREIGN DATA WRAPPER postgres_fdw; -SET ROLE :ROLE_1; - -CREATE TABLE standalone(time TIMESTAMPTZ, device INT, value FLOAT); -SELECT * FROM create_hypertable('standalone','time'); -\set ON_ERROR_STOP 0 --- Throw ERROR for non-existing data node -SELECT * FROM _timescaledb_functions.ping_data_node('data_node_123456789'); --- ERROR on NULL -SELECT * FROM _timescaledb_functions.ping_data_node(NULL); --- ERROR when not passing TimescaleDB data node -SELECT * FROM _timescaledb_functions.ping_data_node('pg_data_node_1'); --- ERROR on attaching to non-distributed hypertable -SELECT * FROM attach_data_node('data_node_1', 'standalone'); -\set ON_ERROR_STOP 1 -DROP TABLE standalone; - --- Some attach data node error cases -\set ON_ERROR_STOP 0 --- Invalid arguments -SELECT * FROM attach_data_node('data_node_1', NULL, true); -SELECT * FROM attach_data_node(NULL, 'disttable', true); - --- Deleted data node -SELECT * FROM attach_data_node('data_node_2', 'disttable'); - --- Attaching to an already attached data node without 'if_not_exists' -SELECT * FROM attach_data_node('data_node_1', 'disttable', false); - --- Attaching a data node to another data node -\c :DN_DBNAME_1 -SELECT * FROM attach_data_node('data_node_4', 'disttable'); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; - -\set ON_ERROR_STOP 1 - --- Attach if not exists -SELECT * FROM attach_data_node('data_node_1', 'disttable', true); - --- Should repartition too. First show existing number of slices in --- 'device' dimension -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE num_slices IS NOT NULL -AND column_name = 'device'; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_4', host => 'localhost', database => :'DN_DBNAME_4', - if_not_exists => true); --- Now let ROLE_1 use data_node_4 since it owns this "disttable" -GRANT USAGE - ON FOREIGN SERVER data_node_4 - TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SELECT * FROM attach_data_node('data_node_4', 'disttable'); --- Recheck that ownership on data_node_4 is proper -SELECT * FROM test.remote_exec(NULL, $$ SELECT tablename, tableowner from pg_catalog.pg_tables where tablename = 'disttable'; $$); - --- Show updated number of slices in 'device' dimension. -SELECT column_name, num_slices -FROM _timescaledb_catalog.dimension -WHERE num_slices IS NOT NULL -AND column_name = 'device'; - --- Clean up -DROP TABLE disttable; -SELECT * FROM delete_data_node('data_node_4'); - -SET ROLE :ROLE_1; --- Creating a distributed hypertable without any servers should fail -CREATE TABLE disttable(time timestamptz, device int, temp float); - -\set ON_ERROR_STOP 0 --- Creating a distributed hypertable without any data nodes should fail -SELECT * FROM create_distributed_hypertable('disttable', 'time', data_nodes => '{ }'); -\set ON_ERROR_STOP 1 - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_1'); -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -SELECT * FROM test.show_subtables('disttable'); -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; - -\set ON_ERROR_STOP 0 --- No data nodes remain, so should fail -SELECT * FROM create_distributed_hypertable('disttable', 'time'); -\set ON_ERROR_STOP 1 - --- These data nodes have been deleted, so safe to remove their databases. -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -DROP DATABASE :DN_DBNAME_4 WITH (FORCE); - --- there should be no data nodes -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - --- let's add some -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -DROP TABLE disttable; - -CREATE TABLE disttable(time timestamptz, device int, temp float); - -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 2, - replication_factor => 2, - data_nodes => '{"data_node_1", "data_node_2", "data_node_3"}'); - --- Create some chunks on all the data_nodes -INSERT INTO disttable VALUES - ('2019-02-02 10:45', 1, 23.4), - ('2019-05-23 10:45', 4, 14.9), - ('2019-07-23 10:45', 8, 7.6); - -SELECT * FROM test.show_subtables('disttable'); -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM _timescaledb_catalog.hypertable_data_node; -SELECT * FROM _timescaledb_catalog.chunk_data_node; -SELECT * FROM hypertable_partitions; - --- Add additional hypertable -CREATE TABLE disttable_2(time timestamptz, device int, temp float); - -SELECT * FROM create_distributed_hypertable('disttable_2', 'time', 'device', 2, replication_factor => 2, data_nodes => '{"data_node_1", "data_node_2", "data_node_3"}'); - -CREATE TABLE devices(device int, name text); - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - --- Block one data node for specific hypertable -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', 'disttable'); - --- Block one data node for all hypertables -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1'); - -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - --- insert more data -INSERT INTO disttable VALUES - ('2019-08-02 10:45', 1, 14.4), - ('2019-08-15 10:45', 4, 14.9), - ('2019-08-26 10:45', 8, 17.6); - --- no new chunks on data_node_1 -SELECT * FROM _timescaledb_catalog.chunk_data_node; - --- some ERROR cases -\set ON_ERROR_STOP 0 --- Will error due to under-replication -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_2'); --- can't block/allow non-existing data node -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_12345', 'disttable'); -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_12345', 'disttable'); --- NULL data node -SELECT * FROM timescaledb_experimental.block_new_chunks(NULL, 'disttable'); -SELECT * FROM timescaledb_experimental.allow_new_chunks(NULL, 'disttable'); --- can't block/allow on non hypertable -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', 'devices'); -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_1', 'devices'); -\set ON_ERROR_STOP 1 - --- Force block all data nodes. Dimension partition information should --- be updated to elide blocked data nodes -SELECT * FROM hypertable_partitions; -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_2', force => true); -SELECT * FROM hypertable_partitions; -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_1', force => true); -SELECT * FROM hypertable_partitions; -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_3', force => true); -SELECT * FROM hypertable_partitions; - --- All data nodes are blocked -SELECT * FROM _timescaledb_catalog.hypertable_data_node; - -\set ON_ERROR_STOP 0 --- insert should fail b/c all data nodes are blocked -INSERT INTO disttable VALUES ('2019-11-02 02:45', 1, 13.3); -\set ON_ERROR_STOP 1 - --- unblock data nodes for all hypertables -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_1'); -SELECT * FROM hypertable_partitions; -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_2'); -SELECT * FROM hypertable_partitions; -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_3'); -SELECT * FROM hypertable_partitions; - -SELECT table_name, node_name, block_chunks -FROM _timescaledb_catalog.hypertable_data_node dn, -_timescaledb_catalog.hypertable h -WHERE dn.hypertable_id = h.id -ORDER BY table_name; - --- Detach should work b/c disttable_2 has no data and more data nodes --- than replication factor -SELECT * FROM detach_data_node('data_node_2', 'disttable_2'); - -\set ON_ERROR_STOP 0 --- can't detach non-existing data node -SELECT * FROM detach_data_node('data_node_12345', 'disttable'); --- NULL data node -SELECT * FROM detach_data_node(NULL, 'disttable'); --- Can't detach data node_1 b/c it contains data for disttable -SELECT * FROM detach_data_node('data_node_1'); --- can't detach already detached data node -SELECT * FROM detach_data_node('data_node_2', 'disttable_2'); -SELECT * FROM detach_data_node('data_node_2', 'disttable_2', if_attached => false); --- can't detach b/c of replication factor for disttable_2 -SELECT * FROM detach_data_node('data_node_3', 'disttable_2'); --- can't detach non hypertable -SELECT * FROM detach_data_node('data_node_3', 'devices'); -\set ON_ERROR_STOP 1 - --- do nothing if node is not attached -SELECT * FROM detach_data_node('data_node_2', 'disttable_2', if_attached => true); - --- force detach data node to become under-replicated for new data -SELECT * FROM hypertable_partitions; -SELECT * FROM detach_data_node('data_node_3', 'disttable_2', force => true); --- Dimension partitions should be updated to no longer list the data --- node for the hypertable -SELECT * FROM hypertable_partitions; - -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; --- force detach data node with data -SELECT * FROM detach_data_node('data_node_3', 'disttable', force => true); - --- chunk and hypertable metadata should be deleted as well -SELECT * FROM _timescaledb_catalog.chunk_data_node; -SELECT table_name, node_name, block_chunks -FROM _timescaledb_catalog.hypertable_data_node dn, -_timescaledb_catalog.hypertable h -WHERE dn.hypertable_id = h.id -ORDER BY table_name; - --- detached data_node_3 should not show up any more -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - -\set ON_ERROR_STOP 0 --- detaching data node with last data replica should ERROR even when forcing -SELECT * FROM detach_data_node('server_2', 'disttable', force => true); -\set ON_ERROR_STOP 1 - --- drop all chunks -SELECT * FROM drop_chunks('disttable', older_than => '2200-01-01 00:00'::timestamptz); -SELECT foreign_table_name, foreign_server_name -FROM information_schema.foreign_tables -ORDER BY foreign_table_name; - -SELECT * FROM detach_data_node('data_node_2', 'disttable', force => true); - --- Let's add more data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_4', host => 'localhost', database => :'DN_DBNAME_4'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_5', host => 'localhost', database => :'DN_DBNAME_5'); -GRANT ALL ON FOREIGN SERVER data_node_4, data_node_5 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Create table as super user -SET ROLE :ROLE_SUPERUSER; -CREATE TABLE disttable_3(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_3', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5"}'); - -SET ROLE :ROLE_1; -CREATE TABLE disttable_4(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_4', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5"}'); - -\set ON_ERROR_STOP 0 --- error due to missing permissions -SELECT * FROM detach_data_node('data_node_4', 'disttable_3'); -SELECT * FROM timescaledb_experimental.block_new_chunks('data_node_4', 'disttable_3'); -SELECT * FROM timescaledb_experimental.allow_new_chunks('data_node_4', 'disttable_3'); -\set ON_ERROR_STOP 1 - --- detach table(s) where user has permissions, otherwise show --- NOTICE. Drop hypertables on data nodes in the process. Drop a --- hypertable on a data node manually to ensure the command can handle --- non-existing hypertables. -CREATE TABLE disttable_5(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('disttable_5', 'time', replication_factor => 1, data_nodes => '{"data_node_4", "data_node_5" }'); -SELECT * FROM test.remote_exec('{ data_node_4 }', $$ SELECT hypertable_name, owner FROM timescaledb_information.hypertables; $$); -CALL distributed_exec($$ DROP TABLE disttable_4 $$, '{ data_node_4 }'); -RESET ROLE; -CALL distributed_exec(format('ALTER TABLE disttable_5 OWNER TO %s', :'ROLE_CLUSTER_SUPERUSER'), '{ data_node_4 }'); -SET ROLE :ROLE_1; --- test first detach without permission to drop the remote data -\set ON_ERROR_STOP 0 -SELECT * FROM detach_data_node('data_node_4', drop_remote_data => true); -\set ON_ERROR_STOP 1 - --- detach should work with permissions -RESET ROLE; -CALL distributed_exec(format('ALTER TABLE disttable_5 OWNER TO %s', :'ROLE_1'), '{ data_node_4 }'); -SET ROLE :ROLE_1; -SELECT * FROM detach_data_node('data_node_4', drop_remote_data => true); - --- Hypertables user had permissions for should be dropped on data nodes -SELECT * FROM test.remote_exec('{ data_node_4 }', $$ SELECT hypertable_name, owner FROM timescaledb_information.hypertables; $$); - --- Cleanup -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node('data_node_1', force =>true); -SELECT * FROM delete_data_node('data_node_2', force =>true); -SELECT * FROM delete_data_node('data_node_3', force =>true); - -SET ROLE :ROLE_1; -\set ON_ERROR_STOP 0 --- Cannot delete a data node which is attached to a table that we don't --- have owner permissions on -SELECT * FROM delete_data_node('data_node_4', force =>true); -SELECT * FROM delete_data_node('data_node_5', force =>true); -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_CLUSTER_SUPERUSER; -DROP TABLE disttable_3; - --- Now we should be able to delete the data nodes -SELECT * FROM delete_data_node('data_node_4', force =>true); -SELECT * FROM delete_data_node('data_node_5', force =>true); - -\set ON_ERROR_STOP 0 --- Should fail because host has to be provided. -SELECT * FROM add_data_node('data_node_6'); -\set ON_ERROR_STOP 1 - --- --- Test timescale extension version check during add_data_node() --- and create_distributed_hypertable() calls. --- --- Use mock extension and create basic function wrappers to --- establish connection to a data node. --- -RESET ROLE; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -CREATE DATABASE :DN_DBNAME_1 OWNER :ROLE_1; - -\c :DN_DBNAME_1 -CREATE SCHEMA _timescaledb_functions; -GRANT ALL ON SCHEMA _timescaledb_functions TO :ROLE_1; - -CREATE FUNCTION _timescaledb_functions.set_dist_id(uuid UUID) - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; - -CREATE FUNCTION _timescaledb_functions.set_peer_dist_id(uuid UUID) - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; - -CREATE FUNCTION _timescaledb_functions.validate_as_data_node() - RETURNS BOOL LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - RETURN true; -END -$BODY$; - -CREATE EXTENSION timescaledb VERSION '0.0.0'; - -\c :TEST_DBNAME :ROLE_SUPERUSER; - -\set ON_ERROR_STOP 0 -SELECT * FROM add_data_node('data_node_1', 'localhost', database => :'DN_DBNAME_1', - bootstrap => false); - --- Testing that it is not possible to use oneself as a data node. This --- is not allowed since it would create a cycle. --- --- We need to use the same owner for this connection as the extension --- owner here to avoid triggering another error. --- --- We cannot use default verbosity here for debugging since the --- version number is printed in some of the notices. -SELECT * FROM add_data_node('data_node_99', host => 'localhost'); -\set ON_ERROR_STOP 1 - - --- Test adding bootstrapped data node where extension owner is different from user adding a data node -SET ROLE :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE :DN_DBNAME_6; -\c :DN_DBNAME_6 -SET client_min_messages = ERROR; --- Creating an extension as superuser -CREATE EXTENSION timescaledb; -RESET client_min_messages; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_3; --- Trying to add data node as non-superuser without GRANT on the --- foreign data wrapper will fail. -\set ON_ERROR_STOP 0 -SELECT * FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6'); -\set ON_ERROR_STOP 1 - -RESET ROLE; -GRANT USAGE ON FOREIGN DATA WRAPPER timescaledb_fdw TO :ROLE_3; -SET ROLE :ROLE_3; - -\set ON_ERROR_STOP 0 --- ROLE_3 doesn't have a password in the passfile and has not way to --- authenticate so adding a data node will still fail. -SELECT * FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6'); -\set ON_ERROR_STOP 1 - --- Providing the password on the command line should work -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_6', host => 'localhost', database => :'DN_DBNAME_6', password => :'ROLE_3_PASS'); - -SELECT * FROM delete_data_node('data_node_6'); - -RESET ROLE; -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); -DROP DATABASE :DN_DBNAME_4 WITH (FORCE); -DROP DATABASE :DN_DBNAME_5 WITH (FORCE); -DROP DATABASE :DN_DBNAME_6 WITH (FORCE); - - ------------------------------------------------ --- Test alter_data_node() ------------------------------------------------ -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_1', host => 'localhost', database => :'DN_DBNAME_1'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_2', host => 'localhost', database => :'DN_DBNAME_2'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data_node_3', host => 'localhost', database => :'DN_DBNAME_3'); - -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -CREATE TABLE hyper1 (time timestamptz, location int, temp float); -CREATE TABLE hyper2 (LIKE hyper1); -CREATE TABLE hyper3 (LIKE hyper1); -CREATE TABLE hyper_1dim (LIKE hyper1); - -SELECT create_distributed_hypertable('hyper1', 'time', 'location', replication_factor=>1); -SELECT create_distributed_hypertable('hyper2', 'time', 'location', replication_factor=>2); -SELECT create_distributed_hypertable('hyper3', 'time', 'location', replication_factor=>3); -SELECT create_distributed_hypertable('hyper_1dim', 'time', chunk_time_interval=>interval '2 days', replication_factor=>3); - -SELECT setseed(1); -INSERT INTO hyper1 -SELECT t, (abs(timestamp_hash(t::timestamp)) % 3) + 1, random() * 30 -FROM generate_series('2022-01-01 00:00:00'::timestamptz, '2022-01-05 00:00:00', '1 h') t; - -INSERT INTO hyper2 SELECT * FROM hyper1; -INSERT INTO hyper3 SELECT * FROM hyper1; -INSERT INTO hyper_1dim SELECT * FROM hyper1; - --- create view to see the data nodes and default data node of all --- chunks -CREATE VIEW chunk_query_data_node AS -SELECT ch.hypertable_name, format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass AS chunk, ch.data_nodes, fs.srvname default_data_node - FROM timescaledb_information.chunks ch - INNER JOIN pg_foreign_table ft ON (format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass = ft.ftrelid) - INNER JOIN pg_foreign_server fs ON (ft.ftserver = fs.oid) - ORDER BY 1, 2; - -SELECT * FROM chunk_query_data_node; - --- test alter_data_node permissions -\set ON_ERROR_STOP 0 --- must be owner to alter a data node -SELECT * FROM alter_data_node('data_node_1', available=>false); -SELECT * FROM alter_data_node('data_node_1', port=>8989); -\set ON_ERROR_STOP 1 - --- query some data from all hypertables to show its working before --- simulating the node being down -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - --- simulate a node being down by renaming the database for --- data_node_1, but for that to work we need to reconnect the backend --- to clear out the connection cache -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -ALTER DATABASE :DN_DBNAME_1 RENAME TO data_node_1_unavailable; -\set ON_ERROR_STOP 0 -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; -\set ON_ERROR_STOP 1 - --- alter the node as not available -SELECT * FROM alter_data_node('data_node_1', available=>false); - --- the node that is not available for reads should no longer be --- query data node for chunks, except for those that have no --- alternative (i.e., the chunk only has one data node). -SELECT * FROM chunk_query_data_node; - --- queries should work again, except on hyper1 which has no --- replication -\set ON_ERROR_STOP 0 -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -\set ON_ERROR_STOP 1 -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - --- inserts should continue to work and should go to the "live" --- datanodes -INSERT INTO hyper3 VALUES ('2022-01-03 00:00:00', 1, 1); -INSERT INTO hyper3 VALUES ('2022-01-03 00:00:05', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-03 00:00:00', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-03 00:00:05', 1, 1); - --- Check that the metadata on the AN removes the association with --- the "unavailable" DN for existing chunks that are being written into --- above -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); - --- Also, inserts should work if going to a new chunk -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:00', 1, 1); -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:05', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:00', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:05', 1, 1); - --- Also check that new chunks only use the "available" DNs -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); - --- Updates/Deletes should also work -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:05'; -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper3 WHERE time = '2022-01-03 00:00:05'; -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -SELECT * FROM hyper_1dim WHERE time = '2022-01-03 00:00:05'; - --- Inserts directly into chunks using FDW should also work and should go to the --- available DNs appropriately -INSERT INTO _timescaledb_internal._dist_hyper_12_24_chunk VALUES ('2022-01-11 00:00:00', 1, 1); -INSERT INTO _timescaledb_internal._dist_hyper_13_25_chunk VALUES ('2022-01-11 00:00:00', 1, 1); -SELECT * FROM test.remote_exec(ARRAY['data_node_2', 'data_node_3'], $$ SELECT * FROM _timescaledb_internal._dist_hyper_12_24_chunk WHERE time = '2022-01-11 00:00:00'; $$); -SELECT * FROM test.remote_exec(ARRAY['data_node_2', 'data_node_3'], $$ SELECT * FROM _timescaledb_internal._dist_hyper_13_25_chunk WHERE time = '2022-01-11 00:00:00'; $$); - -SELECT * FROM chunk_query_data_node WHERE hypertable_name IN ('hyper3', 'hyper_1dim'); -SELECT hypertable_name, chunk_name, data_nodes FROM timescaledb_information.chunks -WHERE hypertable_name IN ('hyper3', 'hyper_1dim') -AND range_start::timestamptz <= '2022-01-10 00:00:00' -AND range_end::timestamptz > '2022-01-10 00:00:00' -ORDER BY 1, 2; - --- DDL should error out even if one DN is unavailable -\set ON_ERROR_STOP 0 -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; -\set ON_ERROR_STOP 1 - --- Mark all DNs unavailable. Metadata should still retain last DN but all --- activity should fail -SELECT * FROM alter_data_node('data_node_2', available=>false); -SELECT * FROM alter_data_node('data_node_3', available=>false); -\set ON_ERROR_STOP 0 -INSERT INTO hyper3 VALUES ('2022-01-10 00:00:00', 1, 1); -INSERT INTO hyper_1dim VALUES ('2022-01-10 00:00:00', 1, 1); -UPDATE hyper3 SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -UPDATE hyper_1dim SET temp = 10 WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper3 WHERE time = '2022-01-03 00:00:00'; -DELETE FROM hyper_1dim WHERE time = '2022-01-03 00:00:00'; -SELECT count(*) FROM hyper3; -SELECT count(*) FROM hyper_1dim; -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; -\set ON_ERROR_STOP 1 - --- re-enable the data node and the chunks should "switch back" to --- using the data node. However, only the chunks for which the node is --- "primary" should switch to using the data node for queries -ALTER DATABASE data_node_1_unavailable RENAME TO :DN_DBNAME_1; -SELECT * FROM alter_data_node('data_node_1', available=>true); -SELECT * FROM alter_data_node('data_node_2', available=>true); -SELECT * FROM alter_data_node('data_node_3', available=>true); -SELECT * FROM chunk_query_data_node; - ---queries should work again on all tables -SELECT time, location FROM hyper1 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper2 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper3 ORDER BY time LIMIT 1; -SELECT time, location FROM hyper_1dim ORDER BY time LIMIT 1; - --- DDL should also work again -ALTER TABLE hyper3 ADD COLUMN temp2 int; -ALTER TABLE hyper_1dim ADD COLUMN temp2 int; - --- save old port so that we can restore connectivity after we test --- changing the connection information for the data node -WITH options AS ( - SELECT unnest(options) opt - FROM timescaledb_information.data_nodes - WHERE node_name = 'data_node_1' -) -SELECT split_part(opt, '=', 2) AS old_port -FROM options WHERE opt LIKE 'port%' \gset - --- also test altering host, port and database -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; -SELECT * FROM alter_data_node('data_node_1', available=>true, host=>'foo.bar', port=>8989, database=>'new_db'); - -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; --- just show current options: -SELECT * FROM alter_data_node('data_node_1'); - -DROP TABLE hyper1; -DROP TABLE hyper2; -DROP TABLE hyper3; -DROP TABLE hyper_1dim; - -\set ON_ERROR_STOP 0 --- test some error cases -SELECT * FROM alter_data_node(NULL); -SELECT * FROM alter_data_node('does_not_exist'); -SELECT * FROM alter_data_node('data_node_1', port=>89000); --- cannot delete data node with "drop_database" since configuration is wrong -SELECT delete_data_node('data_node_1', drop_database=>true); -\set ON_ERROR_STOP 1 - --- restore configuration for data_node_1 -SELECT * FROM alter_data_node('data_node_1', host=>'localhost', port=>:old_port, database=>:'DN_DBNAME_1'); -SELECT node_name, options FROM timescaledb_information.data_nodes order by node_name; - -DROP VIEW chunk_query_data_node; - --- create new session to clear out connection cache -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT delete_data_node('data_node_1', drop_database=>true); -SELECT delete_data_node('data_node_2', drop_database=>true); -SELECT delete_data_node('data_node_3', drop_database=>true); diff --git a/tsl/test/sql/data_node_bootstrap.sql b/tsl/test/sql/data_node_bootstrap.sql deleted file mode 100644 index a009136ffc4..00000000000 --- a/tsl/test/sql/data_node_bootstrap.sql +++ /dev/null @@ -1,492 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER; -CREATE OR REPLACE FUNCTION show_data_nodes() -RETURNS TABLE(data_node_name NAME, host TEXT, dbname NAME) -AS :TSL_MODULE_PATHNAME, 'ts_test_data_node_show' LANGUAGE C; - --- Fetch the encoding, collation, and ctype as quoted strings into --- variables. -SELECT QUOTE_LITERAL(PG_ENCODING_TO_CHAR(encoding)) AS enc - , QUOTE_LITERAL(datcollate) AS coll - , QUOTE_LITERAL(datctype) AS ctype - FROM pg_database - WHERE datname = current_database() - \gset - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); - --- Ensure database and extensions are installed and have the correct --- encoding, ctype and collation. -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SELECT extname, extnamespace::regnamespace FROM pg_extension e WHERE extname = 'timescaledb'; -SELECT PG_ENCODING_TO_CHAR(encoding) = :enc - , datcollate = :coll - , datctype = :ctype - FROM pg_database - WHERE datname = current_database(); - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; --- After delete_data_node, the database and extension should still --- exist on the data node -SELECT * FROM delete_data_node('bootstrap_test'); -SELECT * FROM show_data_nodes(); - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; - -SELECT extname, extnamespace::regnamespace FROM pg_extension e WHERE extname = 'timescaledb'; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 --- Trying to add the data node again should fail, with or without --- bootstrapping. -SELECT add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap=>false); -SELECT add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); -\set ON_ERROR_STOP 0 - -DROP DATABASE bootstrap_test WITH (FORCE); - ----------------------------------------------------------------------- --- Bootstrap the database and check that calling it without --- bootstrapping does not find any problems. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -SELECT * FROM show_data_nodes(); - -SELECT * FROM delete_data_node('bootstrap_test'); - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; --- This should show dist_uuid row on the deleted node since that is --- not removed by delete_data_node. -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - --- Delete the dist_uuid so that we can try to re-add it without --- bootstrapping. -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); - -\set ON_ERROR_STOP 0 --- Dropping the database with delete_data_node should not work in a --- transaction block since it is non-transactional. -BEGIN; -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -ROLLBACK; -\set ON_ERROR_STOP 1 - -CREATE TABLE conditions (time timestamptz, device int, temp float); -SELECT create_distributed_hypertable('conditions', 'time', 'device'); - -\set ON_ERROR_STOP 0 --- Should fail because the data node is the last one -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -\set ON_ERROR_STOP 1 - --- Add another data node -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test_2', host => 'localhost', database => 'bootstrap_test_2', bootstrap => true); -SELECT attach_data_node('bootstrap_test_2', 'conditions'); - --- Insert some data into the node -INSERT INTO conditions VALUES ('2021-12-01 10:30', 2, 20.3); - -\set ON_ERROR_STOP 0 --- Should fail because the data node still holds data -SELECT * FROM delete_data_node('bootstrap_test_2', drop_database => true); -\set ON_ERROR_STOP 1 - --- Data node's database still exists after failure to delete -SELECT count(*) FROM pg_database WHERE datname = 'bootstrap_test_2'; - --- Delete the chunks so that we can delete the data node -SELECT drop_chunks('conditions', older_than => '2022-01-01'::timestamptz); - -SELECT * FROM delete_data_node('bootstrap_test_2', drop_database => true); - --- The data node's database is dropped -SELECT count(*) FROM pg_database WHERE datname = 'bootstrap_test_2'; - -SELECT data_nodes FROM timescaledb_information.hypertables -WHERE hypertable_name = 'conditions'; - --- Using the drop_database option when there are active connections to --- the data node should fail. But any connections in the current --- session should be cleared when dropping the database. To test that --- the connection is cleared, first create a connection in the --- connection cache by inserting some data -INSERT INTO conditions VALUES ('2021-12-01 10:30', 1, 20.3); -DROP TABLE conditions; - --- Now drop the data node and it should clear the connection from the --- cache first -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); - -\set ON_ERROR_STOP 0 --- Dropping the database now should fail since it no longer exists -DROP DATABASE bootstrap_test WITH (FORCE); -\set ON_ERROR_STOP 1 - --- Adding the data node again should work -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); --- Now drop the database manually before using the drop_database option -DROP DATABASE bootstrap_test WITH (FORCE); -\set ON_ERROR_STOP 0 --- Expect an error since the database does not exist. -SELECT * FROM delete_data_node('bootstrap_test', drop_database => true); -\set ON_ERROR_STOP 1 - --- Delete it without the drop_database option set since the database --- was manually deleted. -SELECT * FROM delete_data_node('bootstrap_test'); - ----------------------------------------------------------------------- --- Do a manual bootstrap of the data node and check that it can be --- added. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); - -SELECT * FROM delete_data_node('bootstrap_test'); -DROP DATABASE bootstrap_test WITH (FORCE); - ----------------------------------------------------------------------- --- Do a manual bootstrap of the data node and check that it can be --- added even when bootstrap is true. This is to check that we can --- bootstrap a database with an extension already installed. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); - -SELECT * FROM delete_data_node('bootstrap_test'); -DROP DATABASE bootstrap_test WITH (FORCE); - ----------------------------------------------------------------------- --- Create a database and check that a mismatching encoding is caught --- when bootstrapping (since it will skip creating the database). -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -CREATE DATABASE bootstrap_test - ENCODING SQL_ASCII - LC_COLLATE 'C' - LC_CTYPE 'C' - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; - -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -\set ON_ERROR_STOP 1 - -DROP DATABASE bootstrap_test WITH (FORCE); - ----------------------------------------------------------------------- --- Do a manual bootstrap of the data but check that a mismatching --- encoding, ctype, or collation will be caught. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Pick an alternative locale for testing from the list of installed --- collations. This locale needs to be differnt from the current --- database's locale. We pick it from the list of collations in a --- platform agnostic way since, e.g., Linux and Windows have very --- different locale names. -SELECT QUOTE_LITERAL(c.collctype) AS other_locale - FROM pg_collation c, pg_database d - WHERE c.collencoding = d.encoding - AND d.datctype != c.collctype - AND d.datname = current_database() - ORDER BY c.oid DESC - LIMIT 1 - \gset - -CREATE DATABASE bootstrap_test - ENCODING SQL_ASCII - LC_COLLATE 'C' - LC_CTYPE 'C' - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -\set ON_ERROR_STOP 1 - -DROP DATABASE bootstrap_test WITH (FORCE); - -CREATE DATABASE bootstrap_test - ENCODING :"enc" - LC_COLLATE :other_locale - LC_CTYPE :ctype - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -\set ON_ERROR_STOP 1 - -DROP DATABASE bootstrap_test WITH (FORCE); - -CREATE DATABASE bootstrap_test - ENCODING :"enc" - LC_COLLATE :coll - LC_CTYPE :other_locale - TEMPLATE template0 - OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -\set ON_ERROR_STOP 1 - -DROP DATABASE bootstrap_test WITH (FORCE); - ------------------------------------------------------------------------ --- Bootstrap the database and remove it. Check that the missing --- database is caught when adding the node and not bootstrapping. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -SELECT * FROM show_data_nodes(); -SELECT * FROM delete_data_node('bootstrap_test'); -DROP DATABASE bootstrap_test WITH (FORCE); - -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -\set ON_ERROR_STOP 1 - ------------------------------------------------------------------------ --- Bootstrap the database and remove the extension. --- --- Check that adding the data node and not bootstrapping will fail --- indicating that the extension is missing. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => true); -SELECT * FROM delete_data_node('bootstrap_test'); -\c bootstrap_test :ROLE_SUPERUSER; - -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; -DROP EXTENSION timescaledb CASCADE; -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; - -\set ON_ERROR_STOP 0 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test', bootstrap => false); -\set ON_ERROR_STOP 1 - -DROP DATABASE bootstrap_test WITH (FORCE); - ------------------------------------------------------------------------ --- Create a new access node manually so that we can set a specific --- schema for the access node and then bootstrap a data node partially --- with a non-public schema so that we can see that an error is --- generated. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE DATABASE access_node OWNER :ROLE_CLUSTER_SUPERUSER; - -\c access_node :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER; -CREATE EXTENSION timescaledb WITH SCHEMA ts_non_default CASCADE; -SET client_min_messages TO NOTICE; - --- Show the schema for the extension to verify that it is not public. -SELECT extname FROM pg_extension WHERE extname = 'timescaledb'; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -CREATE DATABASE bootstrap_test OWNER :ROLE_CLUSTER_SUPERUSER; - -\c bootstrap_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE SCHEMA ts_non_default AUTHORIZATION :ROLE_CLUSTER_SUPERUSER; -SET client_min_messages TO NOTICE; - -\c access_node :ROLE_CLUSTER_SUPERUSER - --- Add data node and delete it under error suppression. We want to --- avoid later tests to have random failures because the add succeeds. -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM ts_non_default.add_data_node( - 'bootstrap_test', host => 'localhost', - database => 'bootstrap_test', bootstrap => true); -SELECT * FROM ts_non_default.delete_data_node('bootstrap_test'); -\set ON_ERROR_STOP 1 - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE bootstrap_test WITH (FORCE); -DROP DATABASE access_node WITH (FORCE); - ----------------------------------------------------------------------- --- Test for ongoing transaction -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -BEGIN; -\set ON_ERROR_STOP 0 -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('bootstrap_test', host => 'localhost', database => 'bootstrap_test'); -\set ON_ERROR_STOP 1 -COMMIT; -SELECT * FROM show_data_nodes(); - ---------------------------------------------------------------------- --- Test unusual database names --- --- bootstrap_database = 'postgres' -CREATE FUNCTION test_database_name(name TEXT) RETURNS void AS $$ -BEGIN - PERFORM add_data_node('_test1', host => 'localhost', database => name); - PERFORM delete_data_node('_test1'); -END; -$$ LANGUAGE plpgsql; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT test_database_name('Unusual Name'); -SELECT test_database_name(U&'\0441\043B\043E\043D'); - -DROP DATABASE "Unusual Name" WITH (FORCE); -DROP DATABASE U&"\0441\043B\043E\043D" WITH (FORCE); - --- Test Access Node DATABASE DROP NOTICE message --- - --- Make sure the NOTICE message not shown on a DROP DATABASE error -\set ON_ERROR_STOP 0 -DROP DATABASE :TEST_DBNAME WITH (FORCE); -\set ON_ERROR_STOP 1 - -CREATE DATABASE drop_db_test; -\c drop_db_test :ROLE_CLUSTER_SUPERUSER; - -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -SET client_min_messages TO NOTICE; - --- No security label exists -SELECT label FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; - -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('drop_db_test_dn', host => 'localhost', database => 'drop_db_test_dn'); - --- Make sure security label is created -SELECT substr(label, 0, 10) || ':uuid' - FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Check that timescaledb security label cannot be used directly. To --- support pg_dump, we do not print an error when a proper label is --- used, but print an error if something that doesn't look like a --- distributed uuid is used. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11ec-8919-23804e22321a'; -\set ON_ERROR_STOP 0 -\set VERBOSITY default --- No colon -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'bad_label'; --- Bad tag, but still an UUID -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'uuid:4ab3b1bc-438f-11ec-8919-23804e22321a'; --- Length is not correct -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e2232'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e223215'; --- Length is correct, but it contains something that is not a --- hexadecimal digit. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-4x8f-11ec-8919-23804e22321'; --- Total length is correct, but not the right number of hyphens. -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3-1bcd-438f-11ec-8919-23804e22321'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd438f-11ec-8919-23804e223213'; --- Total length is correct, but length of groups is not -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bcd-438f-11ec-8919-23804e22321'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11ec-891-23804e22321ab'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438f-11e-8919-23804e22321ab'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bc-438-11ec-8919-23804e22321ab'; -SECURITY LABEL FOR timescaledb - ON DATABASE drop_db_test - IS 'dist_uuid:4ab3b1bca-438f-11ec-8919-23804e22321'; -\set VERBOSITY terse -\set ON_ERROR_STOP 1 - --- Check that security label functionality is working -CREATE TABLE seclabel_test(id int); -SECURITY LABEL ON TABLE seclabel_test IS 'label'; -DROP TABLE seclabel_test; - --- This will generate NOTICE message -DROP DATABASE drop_db_test WITH (FORCE); -DROP DATABASE drop_db_test_dn WITH (FORCE); - --- Ensure label is deleted after the DROP -SELECT label FROM pg_shseclabel - WHERE objoid = (SELECT oid from pg_database WHERE datname = 'drop_db_test') AND - provider = 'timescaledb'; diff --git a/tsl/test/sql/debug_notice.sql b/tsl/test/sql/debug_notice.sql deleted file mode 100644 index d9eb0fbd2b7..00000000000 --- a/tsl/test/sql/debug_notice.sql +++ /dev/null @@ -1,96 +0,0 @@ --- 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. - --- This test suite is not intended to check the output of the queries --- but rather make sure that they are generated when certain flags are --- enabled or disabled. --- --- The queries below are triggering a call to `tsl_set_rel_pathlist` --- and `get_foreign_upper_paths` respectively, but if that changes, --- they might need to be changed. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - -CREATE TABLE hyper (time timestamptz, device int, location int, temp float); -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device'); - -SET enable_partitionwise_aggregate = ON; - -INSERT INTO hyper VALUES - ('2018-01-19 13:01', 1, 2, 2.3), - ('2018-01-20 15:05', 1, 3, 5.3), - ('2018-02-21 13:01', 3, 4, 1.5), - ('2018-02-28 15:05', 1, 1, 5.6), - ('2018-02-19 13:02', 3, 5, 3.1), - ('2018-02-19 13:02', 2, 3, 6.7), - ('2018-03-08 11:05', 6, 2, 8.1), - ('2018-03-08 11:05', 7, 4, 4.6), - ('2018-03-10 17:02', 5, 5, 5.1), - ('2018-03-10 17:02', 1, 6, 9.1), - ('2018-03-17 12:02', 2, 2, 6.7), - ('2018-04-19 13:01', 1, 2, 7.6), - ('2018-04-20 15:08', 5, 5, 6.4), - ('2018-05-19 13:01', 4, 4, 5.1), - ('2018-05-20 15:08', 5, 1, 9.4), - ('2018-05-30 13:02', 3, 2, 9.0); - --- Update table stats -ANALYZE hyper; - --- Optimizer debug messages shown at debug level 2 -SET client_min_messages TO DEBUG2; - --- Turning on show_rel should show a message --- But disable the code which avoids dist chunk planning -SET timescaledb.debug_allow_datanode_only_path = 'off'; -SET timescaledb.debug_optimizer_flags = 'show_rel'; -SHOW timescaledb.debug_optimizer_flags; - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; - --- Enable session level datanode only path parameter which doesn't --- plan distributed chunk scans unnecessarily -SET timescaledb.debug_allow_datanode_only_path = 'on'; - --- Turning off the show_rel (and turning on another flag) should not --- show a notice on the relations, but show the upper paths. -SET timescaledb.debug_optimizer_flags = 'show_upper=*'; -SHOW timescaledb.debug_optimizer_flags; - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; - --- Turning off both relations should not show anything. -RESET timescaledb.debug_optimizer_flags; -SHOW timescaledb.debug_optimizer_flags; - -SELECT time, device, avg(temp) AS temp -FROM hyper -WHERE time BETWEEN '2018-04-19 00:01' AND '2018-06-01 00:00' -GROUP BY 1, 2 -ORDER BY 1, 2; - -SET client_min_messages TO ERROR; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_api_calls.sql b/tsl/test/sql/dist_api_calls.sql deleted file mode 100644 index 1042b7769cd..00000000000 --- a/tsl/test/sql/dist_api_calls.sql +++ /dev/null @@ -1,123 +0,0 @@ --- 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. - --- Basic testing of API functions on distributed hypertable - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Create a distributed hypertable with data -SET ROLE :ROLE_1; -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -SELECT * FROM disttable ORDER BY time; -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); - --- Test APIs on the distributed hypertable - --- Call drop_chunks -SELECT drop_chunks('disttable', timestamptz '2017-03-01 00:00'); -SELECT * FROM disttable ORDER BY time; -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); - --- Restore the state -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23); -SELECT * FROM disttable ORDER BY time; -SELECT * FROM show_chunks('disttable'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable'); $$); - --- Ensure that move_chunk() and reorder_chunk() functions cannot be used --- with distributed hypertable -SET ROLE TO DEFAULT; -SET client_min_messages TO error; -DROP TABLESPACE IF EXISTS tablespace1; -RESET client_min_messages; -CREATE TABLESPACE tablespace1 OWNER :ROLE_CLUSTER_SUPERUSER LOCATION :TEST_TABLESPACE1_PATH; - -\set ON_ERROR_STOP 0 -SELECT move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_4_chunk', destination_tablespace=>'tablespace1', index_destination_tablespace=>'tablespace1', reorder_index=>'disttable_time_idx', verbose=>TRUE); -SELECT reorder_chunk('_timescaledb_internal._dist_hyper_1_4_chunk', verbose => TRUE); -\set ON_ERROR_STOP 1 - -DROP TABLESPACE tablespace1; - --- Ensure approximate_row_count() works with distributed hypertable --- -SELECT * FROM disttable ORDER BY time; - -ANALYZE disttable; - -SELECT count(*) FROM disttable; -SELECT approximate_row_count('disttable'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT approximate_row_count('disttable'); $$); - --- Test with native replication --- -CREATE TABLE disttable_repl( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable_repl', 'time', 'device', 3, replication_factor => 2); -INSERT INTO disttable_repl VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -SELECT * FROM disttable_repl ORDER BY time; - -SELECT * FROM show_chunks('disttable_repl'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('disttable_repl'); $$); - -SELECT count(*) FROM disttable_repl; -SELECT approximate_row_count('disttable_repl'); - -ANALYZE disttable_repl; -SELECT approximate_row_count('disttable_repl'); - -DROP TABLE disttable_repl; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_backup.sql b/tsl/test/sql/dist_backup.sql deleted file mode 100644 index facec9e6bff..00000000000 --- a/tsl/test/sql/dist_backup.sql +++ /dev/null @@ -1,125 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\ir include/filter_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - --- Import testsupport.sql file to data nodes -\unset ECHO -\o /dev/null -\c :DATA_NODE_1 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_2 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_3 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :TEST_DBNAME :ROLE_SUPERUSER; -\o -SET client_min_messages TO NOTICE; -\set ECHO all - --- test NULL (STRICT function) -SELECT create_distributed_restore_point(NULL); - --- test long restore point name (>= 64 chars) -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('0123456789012345678901234567890123456789012345678901234567890123456789'); -\set ON_ERROR_STOP 1 - --- test super user check -\set ON_ERROR_STOP 0 -SET ROLE :ROLE_1; -SELECT create_distributed_restore_point('test'); -RESET ROLE; -\set ON_ERROR_STOP 1 - --- make sure 2pc are enabled -SET timescaledb.enable_2pc = false; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -\set ON_ERROR_STOP 1 - -SET timescaledb.enable_2pc = true; -SHOW timescaledb.enable_2pc; - --- make sure wal_level is replica or logical -SHOW wal_level; - --- make sure not in recovery mode -SELECT pg_is_in_recovery(); - --- test on single node (not part of a cluster) -CREATE DATABASE dist_rp_test; -\c dist_rp_test :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE dist_rp_test WITH (FORCE); - --- test on data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- test with distributed_exec() -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('SELECT create_distributed_restore_point(''test'')') -$$); -\set ON_ERROR_STOP 1 - --- test on access node -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('dist_rp') ORDER BY node_name; - --- restore point can be have duplicates -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('dist_rp') ORDER BY node_name; - --- make sure each new restore point have lsn greater then previous one (access node lsn) -SELECT restore_point as lsn_1 FROM create_distributed_restore_point('dist_rp_1') WHERE node_type = 'access_node' \gset -SELECT restore_point as lsn_2 FROM create_distributed_restore_point('dist_rp_2') WHERE node_type = 'access_node' \gset -SELECT pg_lsn(:'lsn_2') > pg_lsn(:'lsn_1') as valid_lsn; - --- make sure it is compatible with local restore point -SELECT pg_create_restore_point('dist_rp') as lsn_3 \gset -SELECT pg_lsn(:'lsn_3') > pg_lsn(:'lsn_2') as valid_lsn; - --- test create_distributed_restore_point() when one of the nodes if unavailable -SELECT alter_data_node(:'DATA_NODE_1', available => false); - -\set ON_ERROR_STOP 0 -SELECT create_distributed_restore_point('test'); -\set ON_ERROR_STOP 1 - -SELECT alter_data_node(:'DATA_NODE_1', available => true); -SELECT node_name, node_type, pg_lsn(restore_point) > pg_lsn('0/0') as valid_lsn FROM create_distributed_restore_point('test') ORDER BY node_name; - -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_cagg.sql b/tsl/test/sql/dist_cagg.sql deleted file mode 100644 index 905d280f67c..00000000000 --- a/tsl/test/sql/dist_cagg.sql +++ /dev/null @@ -1,101 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\ir include/filter_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -CREATE SCHEMA some_schema AUTHORIZATION :ROLE_1; - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- test alter_data_node(unvailable) with caggs --- - --- create cagg on distributed hypertable -CREATE TABLE conditions_dist(day timestamptz NOT NULL, temperature INT NOT NULL); -SELECT create_distributed_hypertable('conditions_dist', 'day', chunk_time_interval => INTERVAL '1 day', replication_factor => 2); - -INSERT INTO conditions_dist(day, temperature) -SELECT ts, date_part('month', ts)*100 + date_part('day', ts) -FROM generate_series('2010-01-01 00:00:00 MSK' :: timestamptz, '2010-03-01 00:00:00 MSK' :: timestamptz - interval '1 day', '1 day') as ts; - -CREATE MATERIALIZED VIEW conditions_dist_1m -WITH (timescaledb.continuous, timescaledb.materialized_only = false) AS -SELECT - timescaledb_experimental.time_bucket_ng('1 month', day, 'MSK') AS bucket, - MIN(temperature), - MAX(temperature) -FROM conditions_dist -GROUP BY bucket; - -SELECT * FROM conditions_dist_1m ORDER BY bucket; - --- case 1: ensure select works when data node is unavailable -SELECT alter_data_node(:'DATA_NODE_1'); -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -SELECT * FROM conditions_dist_1m ORDER BY bucket; - --- case 2: ensure cagg can use real-time aggregation while data node is not available -INSERT INTO conditions_dist(day, temperature) -SELECT ts, date_part('month', ts)*100 + date_part('day', ts) -FROM generate_series('2010-03-01 00:00:00 MSK' :: timestamptz, '2010-04-01 00:00:00 MSK' :: timestamptz - interval '1 day', '1 day') as ts; - --- case 3: refreshing a cagg currently doesn't work when a data node is unavailable -\set ON_ERROR_STOP 0 -CALL refresh_continuous_aggregate('conditions_dist_1m', '2010-01-01', '2010-04-01'); -\set ON_ERROR_STOP 1 - --- case 4: ensure that new data is visible using real-time aggregation -SELECT * FROM conditions_dist_1m ORDER BY bucket; - --- case 5: TRUNCATE will not work while data node is not available because invalidations are sent to the data nodes -\set ON_ERROR_STOP 0 -TRUNCATE TABLE conditions_dist; -\set ON_ERROR_STOP 1 - --- case 6: TRUNCATE cagg directly --- --- Fails because it is trying to send invalidation to DN. --- --- note: data in cagg is stored on AN, so the TRUNCATION itself doesn't fail, --- but it fails as a result of the failed invalidation. -\set ON_ERROR_STOP 0 -TRUNCATE conditions_dist_1m; -\set ON_ERROR_STOP 1 - --- case 7: ensure data node update works when it becomes available again -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -SELECT alter_data_node(:'DATA_NODE_1', available => true); - -CALL refresh_continuous_aggregate('conditions_dist_1m', '2010-01-01', '2010-04-01'); - -ALTER MATERIALIZED VIEW conditions_dist_1m SET(timescaledb.materialized_only = false); -SELECT * FROM conditions_dist_1m ORDER BY bucket; - -ALTER MATERIALIZED VIEW conditions_dist_1m SET(timescaledb.materialized_only = true); -SELECT * FROM conditions_dist_1m ORDER BY bucket; - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_commands.sql b/tsl/test/sql/dist_commands.sql deleted file mode 100644 index c326a9e3cae..00000000000 --- a/tsl/test/sql/dist_commands.sql +++ /dev/null @@ -1,285 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\ir include/filter_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - -\des - -RESET ROLE; -CREATE FUNCTION _timescaledb_internal.invoke_distributed_commands() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_invoke_distributed_commands' -LANGUAGE C STRICT; - -CREATE FUNCTION _timescaledb_internal.invoke_faulty_distributed_command() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_invoke_faulty_distributed_command' -LANGUAGE C STRICT; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -SELECT _timescaledb_internal.invoke_distributed_commands(); - -\c :DATA_NODE_1 -\dt -SELECT * FROM disttable1; -\c :DATA_NODE_2 -\dt -SELECT * FROM disttable1; -\c :DATA_NODE_3 -\dt -SELECT * FROM disttable1; -\c :TEST_DBNAME :ROLE_SUPERUSER -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Verify failed insert command gets fully rolled back -\set ON_ERROR_STOP 0 -SELECT _timescaledb_internal.invoke_faulty_distributed_command(); -\set ON_ERROR_STOP 1 - -\c :DATA_NODE_1 -SELECT * from disttable2; -\c :DATA_NODE_2 -SELECT * from disttable2; - --- Test connection session identity -\c :TEST_DBNAME :ROLE_SUPERUSER -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - --- Register_is_access_node_session_on_data_node() function and test that it returns false for --- connections openned by test suite. This simualates behaviour expected --- with a client connections. -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; - -\c :DATA_NODE_1 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - -\c :DATA_NODE_2 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - -\c :DATA_NODE_3 -CREATE OR REPLACE FUNCTION is_access_node_session_on_data_node() -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_dist_util_is_access_node_session_on_data_node' LANGUAGE C; -SELECT is_access_node_session_on_data_node(); - -\c :TEST_DBNAME :ROLE_SUPERUSER -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT is_access_node_session_on_data_node(); - --- Ensure peer dist id is already set and can be set only once -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT * FROM _timescaledb_functions.set_peer_dist_id('77348176-09da-4a80-bc78-e31bdf5e63ec'); $$); -\set ON_ERROR_STOP 1 - --- Repeat is_access_node_session_on_data_node() test again, but this time using connections openned from --- access node to data nodes. Must return true. -SELECT * FROM test.remote_exec(NULL, $$ SELECT is_access_node_session_on_data_node(); $$); - --- Test distributed_exec() - --- Test calling distributed exec via direct function call -RESET ROLE; -CREATE OR REPLACE PROCEDURE distributed_exec_direct_function_call( - query TEXT, - node_list name[] = NULL, - transactional BOOLEAN = TRUE) -AS :TSL_MODULE_PATHNAME, 'ts_test_direct_function_call' LANGUAGE C; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Invalid input -\set ON_ERROR_STOP 0 -\set VERBOSITY default -BEGIN; --- Not allowed in transcation block if transactional=false -CALL distributed_exec_direct_function_call('CREATE TABLE dist_test(id int)', NULL, false); -ROLLBACK; --- multi-dimensional array of data nodes -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{{db_data_node_1}}'); --- Specified, but empty data node array -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{}'); --- Specified, but contains null values -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{db_data_node_1, NULL}'); --- Specified, but not a data node -CALL distributed_exec('CREATE TABLE dist_test(id int)', '{db_data_node_1928}'); -\set VERBOSITY terse -\set ON_ERROR_STOP 1 - --- Make sure dist session is properly set -CALL distributed_exec('DO $$ BEGIN ASSERT(SELECT is_access_node_session_on_data_node()) = true; END; $$;'); - --- Test creating and dropping a table -CALL distributed_exec('CREATE TABLE dist_test (id int)'); -CALL distributed_exec('INSERT INTO dist_test values (7)'); --- Test INSERTING data using empty array of data nodes (same behavior as not specifying). -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from dist_test; $$); -CALL distributed_exec('DROP TABLE dist_test'); -\set ON_ERROR_STOP 0 -CALL distributed_exec('INSERT INTO dist_test VALUES (8)', ARRAY[:'DATA_NODE_1']); -\set ON_ERROR_STOP 1 - --- Test creating and dropping a role -CREATE ROLE dist_test_role; --- Expect this to be an error, since data nodes are created on the same instance -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('CREATE ROLE dist_test_role'); -$$); -\set ON_ERROR_STOP 1 -SELECT * FROM test.remote_exec(NULL, $$ SELECT 1 from pg_catalog.pg_roles WHERE rolname = 'dist_test_role'; $$); -DROP ROLE DIST_TEST_ROLE; -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -CALL distributed_exec('DROP ROLE dist_test_role'); -$$); -\set ON_ERROR_STOP 1 - --- Do not allow to run distributed_exec() on a data nodes -\c :DATA_NODE_1 -\set ON_ERROR_STOP 0 -CALL distributed_exec('SELECT 1'); -\set ON_ERROR_STOP 1 - -\c :TEST_DBNAME :ROLE_SUPERUSER - --- Test health check function output on access node -SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST; - -SELECT * FROM delete_data_node(:'DATA_NODE_1'); -SELECT * FROM delete_data_node(:'DATA_NODE_2'); -SELECT * FROM delete_data_node(:'DATA_NODE_3'); - --- Test health check when no longer an access node (no data nodes) -SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST; - -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - -\set ON_ERROR_STOP 0 --- Calling distributed_exec without data nodes should fail -CALL distributed_exec('SELECT 1'); -CALL distributed_exec('SELECT 1', '{data_node_1}'); -\set ON_ERROR_STOP 1 - --- Test TS execution on non-TSDB server -CREATE EXTENSION postgres_fdw; -CREATE SERVER myserver FOREIGN DATA WRAPPER postgres_fdw - OPTIONS (host 'foo', dbname 'foodb', port '5432'); -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec('{myserver}', $$ SELECT 1; $$); -\set ON_ERROR_STOP 1 -DROP SERVER myserver; -DROP EXTENSION postgres_fdw; - --- Test that transactional behaviour is the default and that it can be --- disabled. --- --- In this case, we only execute it on one data node since we are --- creating a database and multiple creations of the database would --- clash when executed on the same instace. --- --- We prefix the database names with the test file to be able to --- parallelize the test. Not possible right now because there are --- other databases above that prevents this. -\c :TEST_DBNAME :ROLE_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('dist_commands_1', host => 'localhost', database => :'DATA_NODE_1'); -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('dist_commands_2', host => 'localhost', database => :'DATA_NODE_2'); -GRANT USAGE ON FOREIGN SERVER dist_commands_1, dist_commands_2 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; - -\set ON_ERROR_STOP 0 -CALL distributed_exec('CREATE DATABASE dist_commands_magic', - node_list => '{dist_commands_1}'); -\set ON_ERROR_STOP 1 -CALL distributed_exec('CREATE DATABASE dist_commands_magic', - node_list => '{dist_commands_1}', transactional => FALSE); -DROP DATABASE dist_commands_magic WITH (FORCE); - --- Test that distributed_exec honor the 2PC behaviour when starting a --- transaction locally. It should also give an error if attempting to --- execute non-transactionally inside a local transaction. - --- To test that distributed_exec honors transactions, we create a --- table on both data nodes, and then tweak one of the tables so that --- we get a duplicate key when updating the table on both data --- nodes. This should then abort the transaction on all data nodes. -\c :TEST_DBNAME :ROLE_1 -CALL distributed_exec($$ - CREATE TABLE my_table (key INT, value TEXT, PRIMARY KEY (key)); -$$); - -\c :DATA_NODE_1 -INSERT INTO my_table VALUES (1, 'foo'); - -\c :TEST_DBNAME :ROLE_1 -\set ON_ERROR_STOP 0 -BEGIN; -CALL distributed_exec($$ INSERT INTO my_table VALUES (1, 'bar') $$); -COMMIT; -\set ON_ERROR_STOP 1 - --- No changes should be there -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); - --- This should work. -BEGIN; -CALL distributed_exec($$ INSERT INTO my_table VALUES (2, 'bar'); $$); -COMMIT; - --- We should see changes -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); - --- This should fail since we are inside a transaction and asking for --- transactional execution on the remote nodes. Non-transactional --- execution should be outside transactions. -\set ON_ERROR_STOP 0 -BEGIN; -CALL distributed_exec( - $$ INSERT INTO my_table VALUES (3, 'baz') $$, - transactional => FALSE -); -COMMIT; -\set ON_ERROR_STOP 1 - --- We should see no changes -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM my_table; $$); - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); diff --git a/tsl/test/sql/dist_compression.sql.in b/tsl/test/sql/dist_compression.sql.in deleted file mode 100644 index 49cf8802e56..00000000000 --- a/tsl/test/sql/dist_compression.sql.in +++ /dev/null @@ -1,747 +0,0 @@ --- 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. - ---------------------------------------------------- --- Test compression on a distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\ir include/remote_exec.sql -\ir include/compression_utils.sql - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -CREATE TABLE compressed(time timestamptz, device int, temp float); --- Replicate twice to see that compress_chunk compresses all replica chunks -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 2); -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); - -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - -SELECT * FROM timescaledb_information.compression_settings order by attname; -\x -SELECT * FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; -\x - -SELECT test.remote_exec(NULL, $$ -SELECT table_name, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -WHERE table_name = 'compressed'; -$$); - --- There should be no compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - --- Test that compression is rolled back on aborted transaction -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - --- Data nodes should now report compressed chunks -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; --- Abort the transaction -ROLLBACK; - --- No compressed chunks since we rolled back -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; - --- Compress for real this time -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - --- Check that one chunk, and its replica, is compressed -SELECT * from chunk_compression_stats( 'compressed') -ORDER BY chunk_name, node_name; -select * from hypertable_compression_stats('compressed'); - ---- Decompress the chunk and replica -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - --- Compress odd numbered chunks -SELECT compress_chunk(chunk) FROM -( - SELECT *, row_number() OVER () AS rownum - FROM show_chunks('compressed') AS chunk - ORDER BY chunk -) AS t -WHERE rownum % 2 = 1; -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - --- Compress twice to notice idempotent operation -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - --- Compress again to verify errors are ignored -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - --- There should be no uncompressed chunks -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; -SELECT test.remote_exec(NULL, $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; -$$); - --- Decompress the chunks and replicas -SELECT decompress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; - --- Should now be decompressed -SELECT * from chunk_compression_stats('compressed') -ORDER BY chunk_name, node_name; - --- Decompress twice to generate NOTICE that the chunk is already decompressed -SELECT decompress_chunk(chunk, if_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - -\x -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'compressed'; -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; -\x - -SELECT * FROM chunks_detailed_size('compressed'::regclass) -ORDER BY chunk_name, node_name; -SELECT * FROM hypertable_detailed_size('compressed'::regclass) ORDER BY node_name; - --- Disable compression on distributed table tests -ALTER TABLE compressed SET (timescaledb.compress = false); - -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; - -SELECT * FROM timescaledb_information.compression_settings order by attname; - ---Now re-enable compression -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device'); -SELECT table_name, compression_state, compressed_hypertable_id -FROM _timescaledb_catalog.hypertable -ORDER BY 1; -SELECT * FROM timescaledb_information.compression_settings order by attname; -SELECT compress_chunk(chunk, if_not_compressed => true) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk -LIMIT 1; - -SELECT chunk_name, node_name, compression_status -FROM chunk_compression_stats('compressed') -ORDER BY 1, 2; - --- ALTER TABLE on distributed compressed hypertable -ALTER TABLE compressed ADD COLUMN new_coli integer; -ALTER TABLE compressed ADD COLUMN new_colv varchar(30); - -SELECT * FROM _timescaledb_catalog.hypertable_compression -ORDER BY attname; - -SELECT count(*) from compressed where new_coli is not null; - ---insert data into new chunk -INSERT INTO compressed -SELECT '2019-08-01 00:00', 100, 100, 1, 'newcolv' ; - -SELECT count(compress_chunk(ch,true)) FROM show_chunks('compressed') ch; - -SELECT * from compressed where new_coli is not null; - --- Test ALTER TABLE rename column on distributed hypertables -ALTER TABLE compressed RENAME new_coli TO new_intcol ; -ALTER TABLE compressed RENAME device TO device_id ; - -SELECT * FROM test.remote_exec( NULL, - $$ SELECT * FROM _timescaledb_catalog.hypertable_compression - WHERE attname = 'device_id' OR attname = 'new_intcol' and - hypertable_id = (SELECT id from _timescaledb_catalog.hypertable - WHERE table_name = 'compressed' ) ORDER BY attname; $$ ); - --- TEST insert data into compressed chunk -INSERT INTO compressed -SELECT '2019-08-01 01:00', 300, 300, 3, 'newcolv' ; -SELECT * from compressed where new_intcol = 3; - --- We're done with the table, so drop it. -DROP TABLE IF EXISTS compressed CASCADE; - ------------------------------------------------------- --- Test compression policy on a distributed hypertable ------------------------------------------------------- - -CREATE TABLE conditions ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - location2 char(10) NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL - ); -SELECT create_distributed_hypertable('conditions', 'time', chunk_time_interval => '31days'::interval, replication_factor => 2); - ---TEST 1-- ---cannot set policy without enabling compression -- -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval); -\set ON_ERROR_STOP 1 - --- TEST2 -- ---add a policy to compress chunks -- -alter table conditions set (timescaledb.compress, timescaledb.compress_segmentby = 'location', timescaledb.compress_orderby = 'time'); -insert into conditions -select generate_series('2018-12-01 00:00'::timestamp, '2018-12-31 00:00'::timestamp, '1 day'), 'POR', 'klick', 55, 75; - -select add_compression_policy('conditions', '60d'::interval) AS compressjob_id -\gset - -select * from _timescaledb_config.bgw_job where id = :compressjob_id; -select * from alter_job(:compressjob_id, schedule_interval=>'1s'); -select * from _timescaledb_config.bgw_job where id >= 1000 ORDER BY id; --- we want only 1 chunk to be compressed -- -SELECT alter_job(id,config:=jsonb_set(config,'{maxchunks_to_compress}', '1')) -FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - -insert into conditions -select now()::timestamp, 'TOK', 'sony', 55, 75; - --- TEST3 -- ---only the old chunks will get compressed when policy is executed-- -CALL run_job(:compressjob_id); -select chunk_name, node_name, pg_size_pretty(before_compression_total_bytes) before_total, -pg_size_pretty( after_compression_total_bytes) after_total -from chunk_compression_stats('conditions') where compression_status like 'Compressed' order by chunk_name; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY id; - --- TEST 4 -- ---cannot set another policy -\set ON_ERROR_STOP 0 -select add_compression_policy('conditions', '60d'::interval, if_not_exists=>true); -select add_compression_policy('conditions', '60d'::interval); -select add_compression_policy('conditions', '30d'::interval, if_not_exists=>true); -\set ON_ERROR_STOP 1 - ---TEST 5 -- --- drop the policy -- -select remove_compression_policy('conditions'); -select count(*) from _timescaledb_config.bgw_job WHERE id>=1000; - ---TEST 6 -- --- try to execute the policy after it has been dropped -- -\set ON_ERROR_STOP 0 -CALL run_job(:compressjob_id); -\set ON_ERROR_STOP 1 - --- We're done with the table, so drop it. -DROP TABLE IF EXISTS conditions CASCADE; - ---TEST 7 ---compression policy for smallint, integer or bigint based partition hypertable ---smallint tests -CREATE TABLE test_table_smallint(time smallint, val int); -SELECT create_distributed_hypertable('test_table_smallint', 'time', chunk_time_interval => 1, replication_factor => 2); - -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_smallint() RETURNS SMALLINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::SMALLINT' -$$); -SELECT set_integer_now_func('test_table_smallint', 'dummy_now_smallint'); -INSERT INTO test_table_smallint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_smallint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_smallint', 2::int) AS compressjob_id \gset - -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); - -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_smallint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - ---integer tests -CREATE TABLE test_table_integer(time int, val int); -SELECT create_distributed_hypertable('test_table_integer', 'time', chunk_time_interval => 1, replication_factor => 2); - -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_integer() RETURNS INTEGER LANGUAGE SQL IMMUTABLE as 'SELECT 5::INTEGER' -$$); -SELECT set_integer_now_func('test_table_integer', 'dummy_now_integer'); -INSERT INTO test_table_integer SELECT generate_series(1,5), 10; -ALTER TABLE test_table_integer SET (timescaledb.compress); -SELECT add_compression_policy('test_table_integer', 2::int) AS compressjob_id \gset - -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); - -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_integer') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - ---bigint tests -CREATE TABLE test_table_bigint(time bigint, val int); -SELECT create_distributed_hypertable('test_table_bigint', 'time', chunk_time_interval => 1, replication_factor => 2); - -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now_bigint() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT' -$$); -SELECT set_integer_now_func('test_table_bigint', 'dummy_now_bigint'); -INSERT INTO test_table_bigint SELECT generate_series(1,5), 10; -ALTER TABLE test_table_bigint SET (timescaledb.compress); -SELECT add_compression_policy('test_table_bigint', 2::int) AS compressjob_id \gset - -SELECT * FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id; - -CALL run_job(:compressjob_id); -CALL run_job(:compressjob_id); - -SELECT chunk_name, node_name, before_compression_total_bytes, after_compression_total_bytes -FROM chunk_compression_stats('test_table_bigint') -WHERE compression_status LIKE 'Compressed' -ORDER BY chunk_name; - ---TEST8 insert into compressed chunks on dist. hypertable -CREATE TABLE test_recomp_int(time bigint, val int); -SELECT create_distributed_hypertable('test_recomp_int', 'time', chunk_time_interval => 20); - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 100::BIGINT' -$$); -select set_integer_now_func('test_recomp_int', 'dummy_now'); -insert into test_recomp_int select generate_series(1,5), 10; -alter table test_recomp_int set (timescaledb.compress); - -CREATE VIEW test_recomp_int_chunk_status as -SELECT - c.table_name as chunk_name, - c.status as chunk_status -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int'; - ---compress chunks -SELECT compress_chunk(chunk) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; - ---check the status -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - --- insert into compressed chunks of test_recomp_int (using same value for val)-- -insert into test_recomp_int select 10, 10; -SELECT count(*) from test_recomp_int where val = 10; - ---chunk status should change --- -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - -SELECT -c.schema_name || '.' || c.table_name as "CHUNK_NAME" -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' \gset - ---call recompress_chunk directly on distributed chunk -CALL recompress_chunk(:'CHUNK_NAME'::regclass); - ---check chunk status now, should be compressed -SELECT * from test_recomp_int_chunk_status ORDER BY 1; -SELECT count(*) from test_recomp_int; - ---add a policy-- -select add_compression_policy('test_recomp_int', 1::int) AS compressjob_id -\gset ---once again add data to the compressed chunk -insert into test_recomp_int select generate_series(5,7), 10; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; ---run the compression policy job, it will recompress chunks that are unordered -CALL run_job(:compressjob_id); -SELECT count(*) from test_recomp_int; - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT count(*) from test_recomp_int; -RESET timescaledb.enable_per_data_node_queries; - -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - ----run copy tests ---copy data into existing chunk + for a new chunk -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -11, 11 -12, 12 -13, 13 -100, 100 -101, 100 -102, 100 -\. - -SELECT time_bucket(20, time ), count(*) -FROM test_recomp_int -GROUP BY time_bucket( 20, time) ORDER BY 1; - ---another new chunk -INSERT INTO test_recomp_int VALUES( 65, 10); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - ---compress all 3 chunks --- ---check status, unordered chunk status will not change -SELECT compress_chunk(chunk, true) -FROM show_chunks('test_recomp_int') AS chunk -ORDER BY chunk; -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - ---interleave copy into 3 different chunks and check status-- -COPY test_recomp_int FROM STDIN WITH DELIMITER ','; -14, 14 -103, 100 -66, 66 -15, 15 -104, 100 -70, 70 -\. - -SELECT * from test_recomp_int_chunk_status ORDER BY 1; -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; - --- check with per datanode queries disabled -SET timescaledb.enable_per_data_node_queries TO false; -SELECT time_bucket(20, time), count(*) -FROM test_recomp_int -GROUP BY time_bucket(20, time) ORDER BY 1; -RESET timescaledb.enable_per_data_node_queries; - ---check compression_status afterwards-- -CALL recompress_all_chunks('test_recomp_int', 2, true); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - -CALL run_job(:compressjob_id); -SELECT * from test_recomp_int_chunk_status ORDER BY 1; - ---verify that there are no errors if the policy/recompress_chunk is executed again ---on previously compressed chunks -CALL run_job(:compressjob_id); -CALL recompress_all_chunks('test_recomp_int', true); - ---decompress and recompress chunk -\set ON_ERROR_STOP 0 -SELECT decompress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; -CALL recompress_all_chunks('test_recomp_int', 1, false); -\set ON_ERROR_STOP 1 - --- test alter column type with distributed hypertable -\set ON_ERROR_STOP 0 -ALTER TABLE test_table_smallint ALTER COLUMN val TYPE float; -ALTER TABLE test_table_integer ALTER COLUMN val TYPE float; -ALTER TABLE test_table_bigint ALTER COLUMN val TYPE float; -\set ON_ERROR_STOP 1 - ---create a cont agg view on the ht with compressed chunks as well -SELECT compress_chunk(chunk, true) FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk LIMIT 1 )q; - -CREATE MATERIALIZED VIEW test_recomp_int_cont_view -WITH (timescaledb.continuous, - timescaledb.materialized_only=true) -AS SELECT time_bucket(BIGINT '5', "time"), SUM(val) - FROM test_recomp_int - GROUP BY 1 WITH NO DATA; -SELECT add_continuous_aggregate_policy('test_recomp_int_cont_view', NULL, BIGINT '5', '1 day'::interval); -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, NULL); -SELECT * FROM test_recomp_int ORDER BY 1; -SELECT * FROM test_recomp_int_cont_view ORDER BY 1; - ---TEST cagg triggers work on distributed hypertables when we insert into --- compressed chunks. -SELECT -CASE WHEN compress_chunk(chunk, true) IS NOT NULL THEN 'compress' END AS ch - FROM -( SELECT chunk FROM show_chunks('test_recomp_int') AS chunk ORDER BY chunk )q; - -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - ---insert into an existing compressed chunk and a new chunk -SET timescaledb.enable_distributed_insert_with_copy=false; - -INSERT INTO test_recomp_int VALUES (1, 10), (2,10), (3, 10); -INSERT INTO test_recomp_int VALUES(51, 10); - ---refresh the cagg and verify the new results -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - ---repeat test with copy setting turned to true -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO test_recomp_int VALUES (4, 10); - -CALL refresh_continuous_aggregate('test_recomp_int_cont_view', NULL, 100); -SELECT * FROM test_recomp_int_cont_view -WHERE time_bucket = 0 or time_bucket = 50 ORDER BY 1; - ---TEST drop one of the compressed chunks in test_recomp_int. The catalog ---tuple for the chunk will be preserved since we have a cagg. --- Verify that status is accurate. -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; -SELECT drop_chunks('test_recomp_int', older_than=> 20::bigint ); -SELECT - c.table_name as chunk_name, - c.status as chunk_status, c.dropped, c.compressed_chunk_id as comp_id -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.chunk c -WHERE h.id = c.hypertable_id and h.table_name = 'test_recomp_int' ORDER BY 1; - --- TEST drop should nuke everything -DROP TABLE test_recomp_int CASCADE; - --- test compression default handling -CREATE TABLE test_defaults(time timestamptz NOT NULL, device_id int); -SELECT create_distributed_hypertable('test_defaults','time'); -ALTER TABLE test_defaults SET (timescaledb.compress,timescaledb.compress_segmentby='device_id'); - --- create 2 chunks -INSERT INTO test_defaults SELECT '2000-01-01', 1; -INSERT INTO test_defaults SELECT '2001-01-01', 1; - --- compress first chunk -SELECT compress_chunk(show_chunks) AS compressed_chunk FROM show_chunks('test_defaults') ORDER BY show_chunks::text LIMIT 1; - -SELECT * FROM test_defaults ORDER BY 1; -ALTER TABLE test_defaults ADD COLUMN c1 int; -ALTER TABLE test_defaults ADD COLUMN c2 int NOT NULL DEFAULT 42; -SELECT * FROM test_defaults ORDER BY 1,2; - --- try insert into compressed and recompress -INSERT INTO test_defaults SELECT '2000-01-01', 2; -SELECT * FROM test_defaults ORDER BY 1,2; -CALL recompress_all_chunks('test_defaults', 1, false); -SELECT * FROM test_defaults ORDER BY 1,2; - --- test dropping columns from compressed -CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); -SELECT create_distributed_hypertable('test_drop','time'); -ALTER TABLE test_drop SET (timescaledb.compress,timescaledb.compress_segmentby='device',timescaledb.compress_orderby='o1,o2'); - --- switch to WARNING only to suppress compress_chunk NOTICEs -SET client_min_messages TO WARNING; - --- create some chunks each with different physical layout -ALTER TABLE test_drop DROP COLUMN f1; -INSERT INTO test_drop SELECT NULL,NULL,'2000-01-01',1,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - -ALTER TABLE test_drop DROP COLUMN f2; --- test non-existant column -\set ON_ERROR_STOP 0 -ALTER TABLE test_drop DROP COLUMN f10; -\set ON_ERROR_STOP 1 -ALTER TABLE test_drop DROP COLUMN IF EXISTS f10; - -INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; -ALTER TABLE test_drop DROP COLUMN f3; -INSERT INTO test_drop SELECT '2003-01-01',3,'o1','o2'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; -ALTER TABLE test_drop ADD COLUMN c1 TEXT; -ALTER TABLE test_drop ADD COLUMN c2 TEXT; -INSERT INTO test_drop SELECT '2004-01-01',4,'o1','o2','c1','c2-4'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; -ALTER TABLE test_drop DROP COLUMN c1; -INSERT INTO test_drop SELECT '2005-01-01',5,'o1','o2','c2-5'; -SELECT count(compress_chunk(chunk,true)) FROM show_chunks('test_drop') chunk; - -RESET client_min_messages; -SELECT * FROM test_drop ORDER BY 1; - --- check dropped columns got removed from catalog --- only c2 should be left in metadata -SELECT attname -FROM _timescaledb_catalog.hypertable_compression htc -INNER JOIN _timescaledb_catalog.hypertable ht - ON ht.id=htc.hypertable_id AND ht.table_name='test_drop' -WHERE attname NOT IN ('time','device','o1','o2') -ORDER BY 1; - --- test ADD COLUMN IF NOT EXISTS on a distributed hypertable -CREATE TABLE metric (time TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL); - -SELECT create_distributed_hypertable('metric', 'time'); -ALTER TABLE metric SET ( -timescaledb.compress, -timescaledb.compress_segmentby = 'dev_id', -timescaledb.compress_orderby = 'time DESC' -); - -INSERT INTO metric(time, val, dev_id) -SELECT s.*, 3.14+1, 1 -FROM generate_series('2021-07-01 00:00:00'::timestamp, - '2021-08-17 00:02:00'::timestamp, '30 s'::interval) s; - -SELECT compress_chunk(chunk) -FROM show_chunks('metric') AS chunk -ORDER BY chunk; - --- make sure we have chunks on all data nodes -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks where hypertable_name like 'metric'; --- perform all combinations --- [IF NOT EXISTS] - [] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; --- [IF NOT EXISTS] - ["medium"] -ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" varchar; --- [] - [] -ALTER TABLE metric ADD COLUMN "medium_1" varchar; --- [] - ["medium_1"] -\set ON_ERROR_STOP 0 -ALTER TABLE metric ADD COLUMN "medium_1" varchar; - -SELECT * FROM metric limit 5; -SELECT * FROM metric where medium is not null; - --- INSERTs operate normally on the added column -INSERT INTO metric (time, val, dev_id, medium) -SELECT s.*, 3.14+1, 1, 'medium_value_text' -FROM generate_series('2021-08-18 00:00:00'::timestamp, - '2021-08-19 00:02:00'::timestamp, '30 s'::interval) s; - -SELECT * FROM metric where medium is not null ORDER BY time LIMIT 1; - --- test alter_data_node(unvailable) with compressed chunks --- - --- create compressed distributed hypertable -CREATE TABLE compressed(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('compressed', 'time', 'device', replication_factor => 3); - --- insert data and get chunks distribution -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE compressed SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); - -SELECT compress_chunk(chunk) -FROM show_chunks('compressed') AS chunk -ORDER BY chunk; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - -SELECT count(*) FROM compressed; - --- make data node unavailable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55433, available => false); -SET ROLE :ROLE_1; - --- update compressed chunks -INSERT INTO compressed SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, random()*80 -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; - --- ensure that chunks associated with unavailable data node 1 --- are removed after being updated -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'compressed'; - -SELECT * from show_chunks('compressed'); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2', :'DATA_NODE_3'], $$ SELECT * from show_chunks('compressed'); $$); - -SELECT count(*) FROM compressed; - --- make data node available again -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT alter_data_node(:'DATA_NODE_1', port => 55432); -SELECT alter_data_node(:'DATA_NODE_1', available => true); -SET ROLE :ROLE_1; - --- ensure that stale chunks being dropped from data node 1 automatically -SELECT * from show_chunks('compressed'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); - -SELECT count(*) FROM compressed; - --- recompress chunks -CALL recompress_all_chunks('compressed', 3, true); - -SELECT count(*) FROM compressed; -SELECT * from show_chunks('compressed'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('compressed'); $$); - -DROP TABLE compressed; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - diff --git a/tsl/test/sql/dist_copy_available_dns.sql b/tsl/test/sql/dist_copy_available_dns.sql deleted file mode 100644 index 097fc59f0f5..00000000000 --- a/tsl/test/sql/dist_copy_available_dns.sql +++ /dev/null @@ -1,155 +0,0 @@ --- 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. - --- Test distributed COPY with a bigger data set to help find rare effects. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 - -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -CREATE VIEW chunk_query_data_node AS -SELECT ch.hypertable_name, format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass AS chunk, ch.data_nodes, fs.srvname default_data_node - FROM timescaledb_information.chunks ch - INNER JOIN pg_foreign_table ft ON (format('%I.%I', ch.chunk_schema, ch.chunk_name)::regclass = ft.ftrelid) - INNER JOIN pg_foreign_server fs ON (ft.ftserver = fs.oid) - ORDER BY 1 DESC, 2 DESC; - -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); --- Aim to about 100 partitions, the data is from 1995 to 2022. -select create_distributed_hypertable('uk_price_paid', 'date', chunk_time_interval => interval '270 day', replication_factor=>3); - -create table uk_price_paid_space2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space2', 'date', 'postcode2', 2, chunk_time_interval => interval '270 day', replication_factor => 2); - -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_space2' LIMIT 5; - -set timescaledb.max_open_chunks_per_insert = 1; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>false); -SET ROLE :ROLE_1; - -set timescaledb.max_open_chunks_per_insert = 2; - --- we will write to the same set of chunks and update AN metadata for down DN -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - -set timescaledb.max_open_chunks_per_insert = 1117; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>true); -SET ROLE :ROLE_1; - -TRUNCATE uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name like 'uk_price_paid%' order by hypertable_name; - --- 0, 1, 2 rows -\copy uk_price_paid from stdin -\. - -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -1'; - -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -2'; - -select count(*) from uk_price_paid; - - -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; - --- Make binary file. -\copy (select * from uk_price_paid) to 'prices-10k.pgbinary' with (format binary); - --- Binary input with binary data transfer. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -create table uk_price_paid_bin(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_bin', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 3); - -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>false); -SET ROLE :ROLE_1; - --- Text input with explicit format option and binary data transfer. This will --- update AN metadata for the down DN -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz' with (format text); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - --- Text input with text data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid_bin' LIMIT 5; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_1', available=>true); -SET ROLE :ROLE_1; - -TRUNCATE uk_price_paid; - -SET timescaledb.enable_distributed_insert_with_copy=false; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_2', available=>false); -SET ROLE :ROLE_1; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_2', available=>true); -SET ROLE :ROLE_1; - -truncate uk_price_paid; -SET timescaledb.enable_distributed_insert_with_copy=true; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM alter_data_node('data_node_3', available=>false); -SET ROLE :ROLE_1; -INSERT INTO uk_price_paid SELECT * FROM uk_price_paid_bin; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; -SELECT * FROM chunk_query_data_node WHERE hypertable_name = 'uk_price_paid' LIMIT 5; - --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_copy_format_long.sql b/tsl/test/sql/dist_copy_format_long.sql deleted file mode 100644 index 44b06b2ee58..00000000000 --- a/tsl/test/sql/dist_copy_format_long.sql +++ /dev/null @@ -1,77 +0,0 @@ --- 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. - --- Test distributed COPY with text/binary format for input and for data transfer --- to data nodes. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 - -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- buffer a lot of rows per message to test buffer expansion -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD copy_rows_per_message '1000'); -SET ROLE :ROLE_1; - - - --- Aim to about 100 partitions, the data is from 1995 to 2022. -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); -select create_distributed_hypertable('uk_price_paid', 'date', 'postcode2', - chunk_time_interval => interval '270 day'); - --- Populate. -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid; -select count(*) from show_chunks('uk_price_paid'); - --- Make binary file. -\copy (select * from uk_price_paid) to 'prices-10k.pgbinary' with (format binary); - --- Binary input with binary data transfer. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -create table uk_price_paid_bin(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_bin', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 2); - -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - --- Text input with explicit format option and binary data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz' with (format text); -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - --- Binary input with text data transfer. Doesn't work. -set timescaledb.dist_copy_transfer_format = 'text'; -\set ON_ERROR_STOP off -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -\set ON_ERROR_STOP on - --- Text input with text data transfer. -\copy uk_price_paid_bin from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*), sum(price), sum(price) / count(*) from uk_price_paid_bin; - --- Nonsensical settings -set timescaledb.dist_copy_transfer_format = 'binary'; -set timescaledb.enable_connection_binary_data = false; -\set ON_ERROR_STOP off -\copy uk_price_paid_bin from 'prices-10k.pgbinary' with (format binary); -\set ON_ERROR_STOP on - --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_copy_long.sql b/tsl/test/sql/dist_copy_long.sql deleted file mode 100644 index 619f7d4b48c..00000000000 --- a/tsl/test/sql/dist_copy_long.sql +++ /dev/null @@ -1,125 +0,0 @@ --- 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. - --- Test distributed COPY with a bigger data set to help find rare effects. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 -\set DN_DBNAME_3 :TEST_DBNAME _3 - -SELECT 1 FROM add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -SELECT 1 FROM add_data_node('data_node_2', host => 'localhost', - database => :'DN_DBNAME_2'); -SELECT 1 FROM add_data_node('data_node_3', host => 'localhost', - database => :'DN_DBNAME_3'); -GRANT USAGE ON FOREIGN SERVER data_node_1, data_node_2, data_node_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DN_DBNAME_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DN_DBNAME_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DN_DBNAME_3 SET parallel_setup_cost TO 1; - --- make sure query push-down is enabled -ALTER DATABASE :DN_DBNAME_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DN_DBNAME_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DN_DBNAME_3 SET enable_partitionwise_aggregate TO true; -SET enable_partitionwise_aggregate TO true; -SET ROLE :ROLE_1; - - -create table uk_price_paid(price integer, "date" date, postcode1 text, postcode2 text, type smallint, is_new bool, duration smallint, addr1 text, addr2 text, street text, locality text, town text, district text, country text, category smallint); --- Aim to about 100 partitions, the data is from 1995 to 2022. -select create_distributed_hypertable('uk_price_paid', 'date', chunk_time_interval => interval '270 day'); - -create table uk_price_paid_space2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space2', 'date', 'postcode2', 2, chunk_time_interval => interval '270 day'); - -create table uk_price_paid_space10(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_space10', 'date', 'postcode2', 10, chunk_time_interval => interval '270 day'); - - -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space2; -\copy uk_price_paid_space2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space2; - -\copy uk_price_paid_space10 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space10; -\copy uk_price_paid_space10 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_space10; - - -set timescaledb.max_open_chunks_per_insert = 1; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - -truncate uk_price_paid; - - -set timescaledb.max_open_chunks_per_insert = 2; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - -truncate uk_price_paid; - - -set timescaledb.max_open_chunks_per_insert = 1117; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-100k-random-1.tsv.gz'; -select count(*) from uk_price_paid; - --- Different replication factors -create table uk_price_paid_r2(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_r2', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 2); - -create table uk_price_paid_r3(like uk_price_paid); -select create_distributed_hypertable('uk_price_paid_r3', 'date', 'postcode2', - chunk_time_interval => interval '90 day', replication_factor => 3); - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name like 'uk_price_paid%' order by hypertable_name; - -\copy uk_price_paid_r2 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_r2; - -\copy uk_price_paid_r3 from program 'zcat < data/prices-10k-random-1.tsv.gz'; -select count(*) from uk_price_paid_r3; - --- 0, 1, 2 rows -\copy uk_price_paid from stdin -\. - -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -1'; - -select count(*) from uk_price_paid; - -\copy uk_price_paid from program 'zcat < data/prices-10k-random-1.tsv.gz | head -2'; - -select count(*) from uk_price_paid; - --- Teardown -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); -DROP DATABASE :DN_DBNAME_3 WITH (FORCE); - diff --git a/tsl/test/sql/dist_ddl.sql b/tsl/test/sql/dist_ddl.sql deleted file mode 100644 index 7ec68fe7ac2..00000000000 --- a/tsl/test/sql/dist_ddl.sql +++ /dev/null @@ -1,1048 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Support for execute_sql_and_filter_server_name_on_error() -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\ir include/filter_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -CREATE SCHEMA some_schema AUTHORIZATION :ROLE_1; - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- Presence of non-distributed hypertables on data nodes should not cause issues -CALL distributed_exec('CREATE TABLE local(time timestamptz, measure int)', ARRAY[:'DATA_NODE_1',:'DATA_NODE_3']); -CALL distributed_exec($$ SELECT create_hypertable('local', 'time') $$, ARRAY[:'DATA_NODE_1',:'DATA_NODE_3']); - --- Import testsupport.sql file to data nodes -\unset ECHO -\o /dev/null -\c :DATA_NODE_1 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_2 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_3 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE ---\c :TEST_DBNAME :ROLE_SUPERUSER; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\o -SET client_min_messages TO NOTICE; -\set ECHO all - -SET ROLE :ROLE_1; -CREATE TABLE disttable(time timestamptz, device int, color int CONSTRAINT color_check CHECK (color > 0), temp float); -CREATE UNIQUE INDEX disttable_pk ON disttable(time, temp); - --- CREATE TABLE -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'temp', replication_factor => 3); -SELECT * FROM test.show_columns('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.show_indexes('disttable'); -SELECT * FROM test.show_triggers('disttable'); - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_columns('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.show_indexes('disttable'); -SELECT * FROM test.show_triggers('disttable'); -$$); - --- ADD CONSTRAINT -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); - --- DROP CONSTRAINT -ALTER TABLE disttable DROP CONSTRAINT device_check; -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); - --- DROP CONSTRAINT pre-created -ALTER TABLE disttable DROP CONSTRAINT color_check; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_constraints('disttable') $$); - --- DROP COLUMN -ALTER TABLE disttable DROP COLUMN color; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_columns('disttable') $$); - --- ADD COLUMN -ALTER TABLE disttable ADD COLUMN description text; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_columns('disttable') $$); - --- CREATE INDEX -CREATE INDEX disttable_description_idx ON disttable (description); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('disttable') $$); - --- TRUNCATE -CREATE TABLE non_disttable1(time timestamptz); -CREATE TABLE non_disttable2(time timestamptz); -SELECT create_hypertable('non_disttable2', 'time'); - --- Truncating two non-distribued hypertables should be OK. -TRUNCATE non_disttable1, non_disttable2; --- Truncating one distributed hypertable should be OK -TRUNCATE disttable; - --- RENAME TO -ALTER TABLE disttable RENAME TO disttable2; - -SELECT 1 FROM pg_tables WHERE tablename = 'disttable2'; -\c :DATA_NODE_1 -SELECT 1 FROM pg_tables WHERE tablename = 'disttable2'; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; -ALTER TABLE disttable2 RENAME TO disttable; -SELECT 1 FROM pg_tables WHERE tablename = 'disttable'; -\c :DATA_NODE_1 -SELECT 1 FROM pg_tables WHERE tablename = 'disttable'; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SET ROLE :ROLE_1; - -SET timescaledb.hide_data_node_name_in_errors = 'on'; - --- SET SCHEMA -\set ON_ERROR_STOP 0 -ALTER TABLE disttable SET SCHEMA some_unexist_schema; -\set ON_ERROR_STOP 1 - --- some_schema was not created on data nodes -\set ON_ERROR_STOP 0 -ALTER TABLE disttable SET SCHEMA some_schema; -\set ON_ERROR_STOP 1 - --- OWNER TO -RESET ROLE; -ALTER TABLE disttable OWNER TO :ROLE_2; - -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable'; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT tableowner FROM pg_tables WHERE tablename = 'disttable'; -$$); - -ALTER TABLE disttable OWNER TO :ROLE_1; -SET ROLE :ROLE_1; - --- Test unsupported operations on distributed hypertable -\set ON_ERROR_STOP 0 - --- test set_replication_factor on non-hypertable -SELECT * FROM set_replication_factor('non_disttable1', 1); --- test set_replication_factor on non-distributed -SELECT * FROM set_replication_factor('non_disttable2', 1); --- test set_replication_factor on NULL hypertable -SELECT * FROM set_replication_factor(NULL, 1); - --- Combining one distributed hypertable with any other tables should --- be blocked since not all nodes might have all tables and we --- currently don't rewrite the command. -TRUNCATE disttable, non_disttable1; -TRUNCATE disttable, non_disttable2; - -CLUSTER disttable USING disttable_description_idx; - -DROP TABLE non_disttable1, disttable; -DROP TABLE disttable, non_disttable2; -DROP TABLE disttable, disttable; - -\set ON_ERROR_STOP 1 - ----------------------------------------------------------------------------------------- --- Test column type change, renaming columns, constraints, indexes, and REINDEX command. ----------------------------------------------------------------------------------------- -ALTER TABLE disttable ALTER COLUMN description TYPE VARCHAR(10); - -ALTER TABLE disttable ADD COLUMN float_col float; -ALTER TABLE disttable ALTER COLUMN float_col TYPE INT USING float_col::int; - -\set ON_ERROR_STOP 0 --- Changing the type of a hash-partitioned column should not be supported -ALTER TABLE disttable ALTER COLUMN temp TYPE numeric; -\set ON_ERROR_STOP 1 - --- Should be able to change if not hash partitioned though -ALTER TABLE disttable ALTER COLUMN time TYPE timestamp; - -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2, 'test'), - ('2017-01-01 09:11', 3, 4.3, 'test'), - ('2017-01-01 08:01', 1, 7.3, 'test'), - ('2017-01-02 08:01', 2, 0.23, 'test'), - ('2018-07-02 08:01', 87, 0.0, 'test'), - ('2018-07-01 06:01', 13, 3.1, 'test'), - ('2018-07-01 09:11', 90, 10303.12, 'test'), - ('2018-07-01 08:01', 29, 64, 'test'); - -SELECT * FROM show_chunks('disttable'); - --- Replica identity -SELECT * FROM test.remote_exec(NULL, -$$ - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname; - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname; -$$); - -ALTER TABLE disttable REPLICA IDENTITY FULL; - -SELECT * FROM test.remote_exec(NULL, -$$ - SELECT relname, relreplident FROM pg_class WHERE relname = 'disttable' ORDER BY relname; - SELECT relname, relreplident FROM show_chunks('disttable') ch INNER JOIN pg_class c ON (ch = c.oid) ORDER BY relname; -$$); - --- Rename column -ALTER TABLE disttable RENAME COLUMN description TO descr; -SELECT * FROM test.show_columns('disttable') -WHERE "Column"='descr'; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, - (SELECT "Column" AS col FROM test.show_columns(chunk.relid) WHERE "Column"='descr') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); - --- Rename constraint -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); -ALTER TABLE disttable RENAME CONSTRAINT device_check TO device_chk; -SELECT * FROM test.show_constraints('disttable') -WHERE "Constraint"='device_chk'; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, - (SELECT "Constraint" AS constr FROM test.show_constraints(chunk.relid) WHERE "Constraint"='device_chk') - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); - --- Rename index -ALTER INDEX disttable_description_idx RENAME to disttable_descr_idx; -SELECT * FROM test.show_indexes('disttable') -WHERE "Index"='disttable_descr_idx'::regclass; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT chunk.relid AS chunk_relid, (test.show_indexes(chunk.relid)).* - FROM (SELECT "Child" AS relid FROM test.show_subtables('disttable') LIMIT 1) chunk -$$); - --- Test REINDEX command with distributed hypertable -\c :DATA_NODE_1 -SELECT * FROM test.show_indexes('_timescaledb_internal._dist_hyper_1_1_chunk'); -SELECT pg_relation_filepath('_timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk'::regclass::oid) AS oid_before_reindex \gset -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; - -REINDEX TABLE disttable; -REINDEX (VERBOSE) TABLE disttable; - -\c :DATA_NODE_1 -SELECT pg_relation_filepath('_timescaledb_internal._dist_hyper_1_1_chunk_disttable_pk'::regclass::oid) AS oid_after_reindex \gset -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; - --- expect chunk index oid to change after the reindex operation -SELECT :'oid_before_reindex' <> :'oid_after_reindex'; - --- CREATE/DROP TRIGGER -CREATE OR REPLACE FUNCTION test_trigger() -RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN -RETURN OLD; -END -$BODY$; - -CREATE TRIGGER disttable_trigger_test -BEFORE INSERT ON disttable -FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -DROP TRIGGER disttable_trigger_test on disttable; -DROP FUNCTION test_trigger; -CALL distributed_exec($$ DROP FUNCTION test_trigger $$); - --- DROP INDEX -\set ON_ERROR_STOP 0 -DROP INDEX disttable_description_idx, disttable_pk; -\set ON_ERROR_STOP 1 - -DROP INDEX disttable_descr_idx; -DROP INDEX disttable_pk; -SELECT * FROM test.show_indexes('disttable'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('disttable') $$); - --- DROP TABLE -DROP TABLE disttable; -SELECT * FROM test.remote_exec(NULL, $$ SELECT 1 FROM pg_tables WHERE tablename = 'disttable' $$); - -DROP TABLE non_disttable1; -DROP TABLE non_disttable2; - --- CREATE SCHEMA tests -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE SCHEMA dist_schema AUTHORIZATION :ROLE_1; - --- make sure schema has been created on each data node -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema'; -$$); - -CREATE TABLE dist_schema.some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('dist_schema.some_dist_table', 'time', replication_factor => 3); -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); - --- DROP SCHEMA -DROP SCHEMA dist_schema CASCADE; -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); - --- make sure schema has been dropped on each data node -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema'; -$$); - --- make sure empty schema schema has been created and then dropped on each data node -CREATE SCHEMA dist_schema_2; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); - -DROP SCHEMA dist_schema_2; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); - --- transactional schema create/drop with local table -BEGIN; - -CREATE SCHEMA dist_schema_3; -CREATE TABLE dist_schema_3.some_dist_table(time timestamptz, device int); - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3'; -$$); - -DROP SCHEMA dist_schema_3 CASCADE; - -ROLLBACK; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_3'; -$$); - --- ALTER SCHEMA RENAME TO -CREATE SCHEMA dist_schema; -CREATE TABLE dist_schema.some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('dist_schema.some_dist_table', 'time', replication_factor => 3); -ALTER SCHEMA dist_schema RENAME TO dist_schema_2; -SELECT * FROM test.remote_exec(NULL, $$ SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'some_dist_table' $$); - --- ALTER SCHEMA OWNER TO -ALTER SCHEMA dist_schema_2 OWNER TO :ROLE_1; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'dist_schema_2'; -$$); - -DROP SCHEMA dist_schema_2 CASCADE; - --- DROP column cascades to index drop -CREATE TABLE some_dist_table(time timestamptz, device int, color int, temp float); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -ALTER TABLE some_dist_table DROP COLUMN device; -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -DROP TABLE some_dist_table; - --- Creation of foreign key on distributed hypertable table will lead --- to error, since non_htable is local -CREATE TABLE non_htable (id int PRIMARY KEY); -CREATE TABLE some_dist_table(time timestamptz, device int REFERENCES non_htable(id)); -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -$$); -\set ON_ERROR_STOP 1 -DROP TABLE some_dist_table; -DROP TABLE non_htable; - --- Test disabling DDL commands on global objects --- -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; -SET client_min_messages TO DEBUG1; - --- CREATE SCHEMA -CREATE SCHEMA schema_global; - --- Ensure SCHEMA is not created on data nodes -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global'; -$$); - --- RENAME SCHEMA -ALTER SCHEMA schema_global RENAME TO schema_global_2; - --- ALTER SCHEMA OWNER TO -ALTER SCHEMA schema_global_2 OWNER TO :ROLE_1; - --- REASSIGN OWNED BY TO -REASSIGN OWNED BY :ROLE_1 TO :ROLE_1; - --- Reset earlier to avoid different debug output between PG versions -RESET client_min_messages; - --- DROP OWNED BY schema_global_2 -DROP OWNED BY :ROLE_1; - --- DROP SCHEMA -CREATE SCHEMA schema_global; -SELECT * FROM test.remote_exec(NULL, $$ -SELECT s.nspname, u.usename -FROM pg_catalog.pg_namespace s -JOIN pg_catalog.pg_user u ON u.usesysid = s.nspowner -WHERE s.nspname = 'schema_global'; -$$); -DROP SCHEMA schema_global; - -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; - --- Transactional DDL tests --- Single-statement transactions - --- BEGIN/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -DROP TABLE some_dist_table; - --- BEGIN/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * FROM test.show_indexes('some_dist_table') $$); -DROP TABLE some_dist_table; - --- DDL with multiple sub-commands (ALTER) -BEGIN; -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_distributed_hypertable('some_dist_table', 'time'); -\set ON_ERROR_STOP 0 --- Mixing SET and other options not supported. This is to protect --- against mixing custom (compression) options with other --- sub-commands. -ALTER TABLE some_dist_table SET (fillfactor = 10), -ADD CONSTRAINT device_check CHECK (device > 0); -\set ON_ERROR_STOP 1 -ROLLBACK; - --- Multi-statement transactions - --- BEGIN/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- BEGIN/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- Nested transactions - --- BEGIN/BEGIN/COMMIT/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- BEGIN/BEGIN/ROLLBACK/COMMIT -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT b; -COMMIT; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- BEGIN/BEGIN/COMMIT/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- BEGIN/BEGIN/ROLLBACK/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -ROLLBACK TO SAVEPOINT b; -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- BEGIN/BEGIN/ABORT/ROLLBACK -CREATE TABLE some_dist_table(time timestamptz, device int); -SELECT * FROM create_hypertable('some_dist_table', 'time', replication_factor => 3); -BEGIN; -SAVEPOINT a; -CREATE INDEX some_dist_device_idx ON some_dist_table (device); -SAVEPOINT b; -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -\set ON_ERROR_STOP 0 -ALTER TABLE some_dist_table ADD CONSTRAINT device_check CHECK (device > 0); -\set ON_ERROR_STOP 1 -ROLLBACK TO SAVEPOINT b; -ROLLBACK TO SAVEPOINT a; -ROLLBACK; -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -SELECT * FROM test.remote_exec(NULL, $$ -SELECT * FROM test.show_indexes('some_dist_table'); -SELECT * FROM test.show_constraints('some_dist_table'); -$$); -DROP TABLE some_dist_table; - --- Test chunks updates -CREATE TABLE disttable(time timestamptz, device int, color int CONSTRAINT color_check CHECK (color > 0), temp float); -CREATE UNIQUE INDEX disttable_pk ON disttable(time); -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => 3); - -INSERT INTO disttable VALUES ('2017-01-01 06:01', 0, 1, 0.0); -SELECT show_chunks('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; - -ALTER TABLE disttable DROP CONSTRAINT color_check; -SELECT * FROM test.show_constraints('disttable'); -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT show_chunks('disttable'); -SELECT * FROM test.show_constraints('disttable'); -SELECT (test.show_constraints(chunk)).* -FROM show_chunks('disttable') AS chunk; -$$); -DROP TABLE disttable; - --- Test event triggers behaviour -CREATE OR REPLACE FUNCTION test_event_trigger_sql_drop_function() RETURNS event_trigger -LANGUAGE plpgsql AS $$ -BEGIN - EXECUTE 'DROP TABLE IF EXISTS unexist_table'; -END -$$; - -\c :TEST_DBNAME :ROLE_SUPERUSER; - -CREATE EVENT TRIGGER test_event_trigger_sqldrop ON sql_drop - WHEN TAG IN ('drop table') - EXECUTE FUNCTION test_event_trigger_sql_drop_function(); - -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Test DROP inside event trigger on local table (should not crash) -CREATE TABLE non_htable (id int PRIMARY KEY); -DROP TABLE non_htable; - -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP EVENT TRIGGER test_event_trigger_sqldrop; -SET ROLE :ROLE_1; - --- Test DDL blocking from non-frontend session --- --- We test only special corner cases since most of this functionality already --- been tested before. --- -CREATE TABLE disttable(time timestamptz, device int); -SELECT * FROM create_hypertable('disttable', 'time', replication_factor => 3); -CREATE INDEX disttable_device_idx ON disttable (device); - --- Test alter replication factor on empty table -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; -SELECT * FROM set_replication_factor('disttable', 1); -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; -SELECT * FROM set_replication_factor('disttable', 1); -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; -SELECT * FROM set_replication_factor('disttable', 2); -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('disttable', 4); -SELECT * FROM set_replication_factor('disttable', 0); -SELECT * FROM set_replication_factor('disttable', NULL); -\set ON_ERROR_STOP 1 -SELECT replication_factor FROM _timescaledb_catalog.hypertable ORDER BY id; - -\c :DATA_NODE_1 -SELECT schemaname, tablename FROM pg_tables WHERE tablename = 'disttable'; -SELECT * FROM test.show_indexes('disttable'); - -\set ON_ERROR_STOP 0 - --- fail to alter replication factor for the table on data node -SELECT * FROM set_replication_factor('disttable', 1); - --- Test TRUNCATE blocked on data node -TRUNCATE disttable; - --- Test ALTER by non-frontend session -ALTER TABLE disttable ADD CONSTRAINT device_check CHECK (device > 0); - --- Test path for delayed relid resolving -ALTER TABLE disttable RENAME TO disttable2; - --- Test for hypertables collected during drop -DROP INDEX disttable_device_idx; -DROP TABLE disttable; - -\set ON_ERROR_STOP 1 - --- Explicitly allow execution -SET timescaledb.enable_client_ddl_on_data_nodes TO true; -DROP INDEX disttable_device_idx; -SELECT * FROM test.show_indexes('disttable'); - -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; - --- Should fail because of the inconsistency -\set ON_ERROR_STOP 0 -DROP INDEX disttable_device_idx; -\set ON_ERROR_STOP 1 - -DROP TABLE disttable; - --- Ensure VACUUM/ANALYZE commands can be run on a data node --- without enabling timescaledb.enable_client_ddl_on_data_nodes guc -CREATE TABLE disttable(time timestamptz NOT NULL, device int); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', replication_factor => 3); -\c :DATA_NODE_1 -ANALYZE disttable; -ANALYZE; -VACUUM disttable; -VACUUM; -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP TABLE disttable; - --- Ensure ANALYZE commands can be run on a set of data nodes --- --- Issue: #4508 --- -CREATE TABLE hyper(time TIMESTAMPTZ, device INT, temp FLOAT); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 4, chunk_time_interval => interval '18 hours', replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); - -INSERT INTO hyper SELECT t, ceil((random() * 5))::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-05'::timestamptz, '1 minute') as t; -ANALYZE hyper; -DROP TABLE hyper; - --- --- Ensure single query multi-statement command is blocked --- --- Issue #4818 --- -CREATE TABLE disttable(time timestamptz NOT NULL, device int); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); - -CREATE OR REPLACE PROCEDURE test_dist_multi_stmt_command() -LANGUAGE plpgsql AS $$ -BEGIN - EXECUTE 'ANALYZE disttable; ANALYZE disttable'; -END -$$; - -SET timescaledb.hide_data_node_name_in_errors = 'on'; - --- unsupported -\set ON_ERROR_STOP 0 -CALL test_dist_multi_stmt_command(); -\set ON_ERROR_STOP 1 - -DROP TABLE disttable; --- --- Test hypertable distributed defaults --- -SHOW timescaledb.hypertable_distributed_default; -SHOW timescaledb.hypertable_replication_factor_default; - -/* CASE1: create_hypertable(distributed, replication_factor) */ - --- defaults are not applied -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -\set ON_ERROR_STOP 0 -SELECT create_hypertable('drf_test', 'time', distributed=>false, replication_factor=>1); -\set ON_ERROR_STOP 1 -SELECT create_hypertable('drf_test', 'time', distributed=>true, replication_factor=>1); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - -/* CASE2: create_hypertable(distributed) */ - --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; - --- create regular hypertable by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- distributed (same as auto) -SET timescaledb.hypertable_distributed_default TO 'distributed'; - --- create regular hypertable by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- local -SET timescaledb.hypertable_distributed_default TO 'local'; - --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>false); -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 - --- create distributed hypertable using replication factor default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', distributed=>true); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - -/* CASE3: create_hypertable(replication_factor) */ - --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; - --- create distributed hypertable when replication_factor > 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- distributed -SET timescaledb.hypertable_distributed_default TO 'distributed'; - --- create distributed hypertable -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- local -SET timescaledb.hypertable_distributed_default TO 'local'; - --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=>2); -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 - --- distributed hypertable member: replication_factor=>-1 -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time', replication_factor=> -1); -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 - -/* CASE4: create_hypertable() */ - --- auto -SET timescaledb.hypertable_distributed_default TO 'auto'; - --- regular by default -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- distributed -SET timescaledb.hypertable_distributed_default TO 'distributed'; - --- distributed hypertable with using default replication factor -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- local -SET timescaledb.hypertable_distributed_default TO 'distributed'; - --- unsupported -\set ON_ERROR_STOP 0 -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_hypertable('drf_test', 'time'); -DROP TABLE drf_test; -\set ON_ERROR_STOP 1 - -/* CASE5: create_distributed_hypertable() default replication factor */ -SET timescaledb.hypertable_distributed_default TO 'auto'; -SET timescaledb.hypertable_replication_factor_default TO 3; - -CREATE TABLE drf_test(time TIMESTAMPTZ NOT NULL); -SELECT create_distributed_hypertable('drf_test', 'time'); -SELECT is_distributed, replication_factor FROM timescaledb_information.hypertables WHERE hypertable_name = 'drf_test'; -DROP TABLE drf_test; - --- test drop_stale_chunks() --- - --- test directly on a data node first -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - -\c :DATA_NODE_1 - --- check call arguments when executed on data node -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.drop_stale_chunks(NULL, NULL); -SELECT _timescaledb_functions.drop_stale_chunks('dn1', NULL); -\set ON_ERROR_STOP 1 - --- direct call to all chunks other then 19, 21 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - -SET client_min_messages TO DEBUG1; -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19, 21]::integer[]); -RESET client_min_messages; - -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - --- ensure that drop_stale_chunks() does not affect local chunks -CREATE TABLE local_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_hypertable('local_test', 'time', 'device', 3); -INSERT INTO local_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('local_test'); -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; - -SET client_min_messages TO DEBUG1; -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[19]::integer[]); -RESET client_min_messages; - -SELECT * from show_chunks('local_test'); -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; -DROP TABLE local_test; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP TABLE dist_test; - --- test from access node -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - --- check call arguments when executed on access node -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.drop_stale_chunks( NULL, NULL); -SELECT _timescaledb_functions.drop_stale_chunks(NULL, array[1,2,3]); -\set ON_ERROR_STOP 1 - --- create stale chunk by dropping them from access node -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_36_chunk; -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_37_chunk; - -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - ----- drop stale chunks 36, 37 on data nodes -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_1'); -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_2'); -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_3'); - -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - --- test drop_stale_chunks() with compressed chunk -ALTER TABLE dist_test set (timescaledb.compress, timescaledb.compress_segmentby = 'device', timescaledb.compress_orderby = 'time'); -SELECT compress_chunk('_timescaledb_internal._dist_hyper_35_38_chunk'); - -\c :DATA_NODE_1 - -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; -SELECT * from show_chunks('dist_test'); - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_35_38_chunk; - -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - --- drop stale chunk 38 -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_1'); -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_2'); -SELECT _timescaledb_functions.drop_stale_chunks(:'DATA_NODE_3'); - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; -SELECT * from show_chunks('dist_test'); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP TABLE dist_test; - --- test alter_data_node() auto drop stale chunks on available --- -CREATE TABLE dist_test(time timestamptz NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3, replication_factor => 3); -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - -SELECT alter_data_node(:'DATA_NODE_1', available => false); - --- create stale chunks -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_36_41_chunk; -DROP FOREIGN TABLE _timescaledb_internal._dist_hyper_36_42_chunk; - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; -SELECT * from show_chunks('dist_test'); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- drop stale chunks by making data node available -SELECT alter_data_node(:'DATA_NODE_1', available => true); - -\c :DATA_NODE_1 -SELECT id, table_name FROM _timescaledb_catalog.chunk ORDER BY id, table_name; -SELECT * from show_chunks('dist_test'); -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -DROP TABLE dist_test; - --- cleanup -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_grant.sql.in b/tsl/test/sql/dist_grant.sql.in deleted file mode 100644 index 1dafeafd452..00000000000 --- a/tsl/test/sql/dist_grant.sql.in +++ /dev/null @@ -1,456 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -CREATE TABLE conditions(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -GRANT SELECT ON conditions TO :ROLE_1; -GRANT INSERT, DELETE ON conditions TO :ROLE_2; -SELECT relname, relacl FROM pg_class WHERE relname = 'conditions'; - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device'); -SELECT has_table_privilege(:'ROLE_1', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'conditions', 'INSERT') AS "INSERT"; - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); - -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT"; - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2')); - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; - --- Check that we can actually execute a select as non-owner -SET ROLE :ROLE_1; -SELECT COUNT(*) FROM conditions; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -GRANT UPDATE ON conditions TO :ROLE_2; -BEGIN; -GRANT TRUNCATE ON conditions TO :ROLE_2; -ROLLBACK; - --- Should have UPDATE, but not TRUNCATE -SELECT has_table_privilege(:'ROLE_2', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_2', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_2', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege(:'ROLE_2', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege(:'ROLE_2', 'conditions', 'TRUNCATE') AS "TRUNCATE"; - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); - --- Add another data node and check that grants are propagated when the --- data node is attached to an existing table. -SELECT node_name, database, node_created, database_created, extension_created FROM add_data_node('data4', host => 'localhost', database => :'DATA_NODE_4'); - -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); -\set ON_ERROR_STOP 1 - -SELECT * FROM attach_data_node('data4', 'conditions'); - -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 -FROM generate_series('2019-02-01 00:00:00'::timestamptz, '2019-03-01 00:00:00', '1 min') AS time; - -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'conditions', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'conditions', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'conditions', 'INSERT') AS "INSERT" - , has_table_privilege('%s', 'conditions', 'UPDATE') AS "UPDATE" - , has_table_privilege('%s', 'conditions', 'TRUNCATE') AS "TRUNCATE"; -$$, :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2', :'ROLE_2')); - --- Check that grants are not propagated when enable_grant_propagation --- is false. -SET timescaledb.enable_grant_propagation = false; - -CREATE TABLE no_grants(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT); -GRANT SELECT ON no_grants TO :ROLE_1; - --- First case is when table is created. Grants should not be propagated. -SELECT * FROM create_distributed_hypertable('no_grants', 'time', 'device'); - -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); - --- Second case is when grants is done on an existing table. The grant --- should not be propagated. -GRANT INSERT ON no_grants TO :ROLE_1; - -SELECT has_table_privilege(:'ROLE_1', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege(:'ROLE_1', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege(:'ROLE_1', 'no_grants', 'INSERT') AS "INSERT"; -SELECT * FROM test.remote_exec(NULL, format($$ - SELECT has_table_privilege('%s', 'no_grants', 'SELECT') AS "SELECT" - , has_table_privilege('%s', 'no_grants', 'DELETE') AS "DELETE" - , has_table_privilege('%s', 'no_grants', 'INSERT') AS "INSERT"; -$$, :'ROLE_1', :'ROLE_1', :'ROLE_1')); - -DROP TABLE conditions; -DROP TABLE no_grants; - --- Check that grants and revokes are copied properly to the chunks and --- that newly created chunks have the right privileges. -CREATE TABLE conditions( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); - --- Create a hypertable and show that it does not have any privileges -SELECT * FROM create_hypertable('conditions', 'time', chunk_time_interval => '5 days'::interval); -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; -\z conditions -\z _timescaledb_internal.*chunk - --- Add privileges and show that they propagate to the chunks -GRANT SELECT, INSERT ON conditions TO PUBLIC; -\z conditions -\z _timescaledb_internal.*chunk - --- Create some more chunks and show that they also get the privileges. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-10 00:00'::timestamp, '2018-12-20 00:00'::timestamp, '1h') AS time; -\z conditions -\z _timescaledb_internal.*chunk - --- Revoke one of the privileges and show that it propagate to the --- chunks. -REVOKE INSERT ON conditions FROM PUBLIC; -\z conditions -\z _timescaledb_internal.*chunk - --- Add some more chunks and show that it inherits the grants from the --- hypertable. -INSERT INTO conditions -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-20 00:00'::timestamp, '2018-12-30 00:00'::timestamp, '1h') AS time; -\z conditions -\z _timescaledb_internal.*chunk - --- Change grants of one chunk explicitly and check that it is possible - -\z _timescaledb_internal._hyper_3_35_chunk -GRANT UPDATE ON _timescaledb_internal._hyper_3_35_chunk TO PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk -REVOKE SELECT ON _timescaledb_internal._hyper_3_35_chunk FROM PUBLIC; -\z _timescaledb_internal._hyper_3_35_chunk - -DROP TABLE conditions; - --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -CREATE TABLE conditions( - time timestamptz, - device int CHECK (device > 0), - temp float, - PRIMARY KEY (time,device) -); - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3); - --- Test that we can create a writer role, assign users to that role, --- and allow the users to insert data and create new chunks. - -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -\set ON_ERROR_STOP 0 -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; -\set ON_ERROR_STOP 1 - -RESET ROLE; -GRANT INSERT ON conditions TO :ROLE_DEFAULT_PERM_USER_2; - -SET ROLE :ROLE_DEFAULT_PERM_USER_2; -INSERT INTO conditions -SELECT time, 1 + (random()*30)::int, random()*80 -FROM generate_series('2019-01-01 00:00:00'::timestamptz, '2019-02-01 00:00:00', '1 min') AS time; - -RESET ROLE; -SELECT current_user; - --- Check that GRANT ALL IN SCHEMA adds privileges to the parent --- and also does so on the foreign chunks in another schema -CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; -CALL distributed_exec($$ CREATE VIEW CHUNK_QRY1 AS SELECT n.nspname as schema, substring(c.relname for 12) as name, pg_catalog.array_to_string(c.relacl, E'\n') AS Access_privileges FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','p') AND c.relname OPERATOR(pg_catalog.~) '^(_dist.*)$' COLLATE pg_catalog.default ORDER BY 1, 2; $$); -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z conditions -SELECT * FROM CHUNK_QRY1; - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\z conditions -SELECT * FROM CHUNK_QRY1; - --- Check that REVOKE ALL IN SCHEMA removes privileges of the parent --- and also does so on foreign chunks in another schema -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z conditions -SELECT * FROM CHUNK_QRY1; - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; -\z conditions -SELECT * FROM CHUNK_QRY1; - --- Create chunks in the same schema as the hypertable and check that --- they also get the same privileges as the hypertable -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -CREATE TABLE measurements( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temperature FLOAT -); - --- Create a distributed hypertable with chunks in the same schema -SELECT * FROM create_distributed_hypertable('public.measurements', 'time', chunk_time_interval => '5 days'::interval, associated_schema_name => 'public'); -INSERT INTO measurements -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; - --- Create a local regular table -CREATE TABLE local(g int primary key, h int); - --- Create a local hypertable -CREATE TABLE conditions_lht(time TIMESTAMPTZ NOT NULL, device INTEGER, temperature FLOAT, humidity FLOAT); -SELECT * FROM create_hypertable('conditions_lht', 'time', chunk_time_interval => '5 days'::interval); -INSERT INTO conditions_lht -SELECT time, (random()*30)::int, random()*80 - 40 -FROM generate_series('2018-12-01 00:00'::timestamp, '2018-12-10 00:00'::timestamp, '1h') AS time; - --- GRANT ALL and check privileges of these mix of local table, local hypertable and distributed hypertable -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; -\z measurements -\z conditions -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; -\z measurements -\z conditions -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - --- REVOKE ALL and check privileges -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -\z measurements -\z conditions -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; - --- Check on one datanode, should be the same on others as well -\c :DATA_NODE_4 :ROLE_CLUSTER_SUPERUSER; -\z measurements -\z conditions -SELECT * FROM CHUNK_QRY1 WHERE schema = 'public'; -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- Test GRANT/REVOKE on DATABASE -SET client_min_messages TO DEBUG1; - --- Test GRANT/REVOKE command being deparsed with the database name and --- being propagated to the data nodes -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER, :ROLE_DEFAULT_PERM_USER; -GRANT TEMP ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER WITH GRANT OPTION; - -REVOKE TEMP ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER CASCADE; -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER RESTRICT; - --- Grant to specific role types -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO PUBLIC; -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_USER; -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO SESSION_USER, :ROLE_CLUSTER_SUPERUSER; --- PG14 added support for CURRENT_ROLE -\set ON_ERROR_STOP 0 -GRANT TEMP, TEMPORARY ON DATABASE :TEST_DBNAME TO CURRENT_ROLE; -\set ON_ERROR_STOP 1 - --- Grant on other database should not be propagated -GRANT CREATE ON DATABASE :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; - --- Prevent mixing databases -\set ON_ERROR_STOP 0 -GRANT CREATE ON DATABASE :TEST_DBNAME, :DATA_NODE_1 TO :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 1 - --- Test disabling DDL commands on global objects -SET timescaledb_experimental.enable_distributed_ddl TO 'off'; - --- ALTER DEFAULT PRIVELEGES -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; - --- GRANT/REVOKE -REVOKE ALL ON DATABASE :TEST_DBNAME FROM :ROLE_CLUSTER_SUPERUSER; -GRANT ALL ON DATABASE :TEST_DBNAME TO :ROLE_CLUSTER_SUPERUSER; - -REVOKE ALL ON SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -GRANT ALL ON SCHEMA public TO :ROLE_DEFAULT_PERM_USER; - -REVOKE ALL ON ALL TABLES IN SCHEMA public FROM :ROLE_DEFAULT_PERM_USER; -GRANT ALL ON ALL TABLES IN SCHEMA public TO :ROLE_DEFAULT_PERM_USER; - -SET timescaledb_experimental.enable_distributed_ddl TO 'on'; -RESET client_min_messages; - --- Test GRANT on foreign server and data node authentication using a --- user mapping -SET ROLE :ROLE_3; -SELECT current_user; -CREATE TABLE disttable_role_3(time timestamptz, device int, temp float); - -\set ON_ERROR_STOP 0 --- Can't create distributed hypertable without GRANTs on foreign servers (data nodes) -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -\set ON_ERROR_STOP 1 - --- Grant USAGE on DATA_NODE_1 (but it is not enough) -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; - -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -\set ON_ERROR_STOP 1 - --- Creating the hypertable should work with GRANTs on both servers. -RESET ROLE; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_2 TO :ROLE_3; -GRANT CREATE ON SCHEMA public TO :ROLE_3; -SET ROLE :ROLE_3; - -\set ON_ERROR_STOP 0 --- Still cannot connect since there is no password in the passfile and --- no user mapping. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -\set ON_ERROR_STOP 1 - -RESET ROLE; -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1 OPTIONS (user :'ROLE_3', password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; - -\set ON_ERROR_STOP 0 --- Still cannot connect since there is only a user mapping for data --- node DATA_NODE_1. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); -\set ON_ERROR_STOP 1 - -RESET ROLE; --- Create user mapping for ROLE_3, but don't specify user in --- options. The "current user" will instead be used when connecting. -CREATE USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2 OPTIONS (password :'ROLE_3_PASS'); -SET ROLE :ROLE_3; - --- User should be able to connect and create the distributed --- hypertable at this point. -SELECT * FROM create_distributed_hypertable('disttable_role_3', 'time', data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2']); - --- Test insert and query -INSERT INTO disttable_role_3 VALUES ('2019-01-01 00:00:00', 1, 23.4); -SELECT * FROM disttable_role_3; - -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_1; -DROP USER MAPPING FOR :ROLE_3 SERVER :DATA_NODE_2; - --- Test altering default privileges -RESET ROLE; --- Should be superuser -SELECT current_user; - -CALL distributed_exec($$ CREATE TABLE nodefprivs (time timestamptz, value int) $$); -SET ROLE :ROLE_1; - -\set ON_ERROR_STOP 0 --- Should fail due to lack of privileges (only insert on one data node --- to make error reporting deterministic) -CALL distributed_exec($$ INSERT INTO nodefprivs VALUES ('2019-01-01 00:00:00', 1) $$, ARRAY[:'DATA_NODE_1']); -\set ON_ERROR_STOP 1 - --- Reset to super user -RESET ROLE; --- Now alter default privileges and create table -ALTER DEFAULT PRIVILEGES GRANT INSERT ON TABLES TO :ROLE_1; -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -CALL distributed_exec($$ CREATE TABLE defprivs (time timestamptz, value int) $$); - --- Switch to the role that was granted default privileges -SET ROLE :ROLE_1; --- Should succeed since user will have insert privileges by default -CALL distributed_exec($$ INSERT INTO defprivs VALUES ('2019-01-01 00:00:00', 1) $$); - -RESET ROLE; -ALTER DEFAULT PRIVILEGES REVOKE INSERT ON TABLES FROM :ROLE_1; --- No default privileges remain -SELECT FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT defaclrole::regrole, defaclobjtype, defaclacl FROM pg_default_acl -$$); -CALL distributed_exec($$ DROP TABLE defprivs $$); - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); -DROP DATABASE :DATA_NODE_4 WITH (FORCE); diff --git a/tsl/test/sql/dist_hypertable.sql.in b/tsl/test/sql/dist_hypertable.sql.in deleted file mode 100644 index af2238a08dd..00000000000 --- a/tsl/test/sql/dist_hypertable.sql.in +++ /dev/null @@ -1,2103 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\unset ECHO -\o /dev/null -\ir include/debugsupport.sql -\ir include/filter_exec.sql -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set DATA_NODE_4 :TEST_DBNAME _4 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - --- View to see dimension partitions. Note RIGHT JOIN to see that --- dimension partitions are cleaned up (deleted) properly. -CREATE VIEW hypertable_partitions AS -SELECT table_name, dimension_id, range_start, data_nodes -FROM _timescaledb_catalog.hypertable h -INNER JOIN _timescaledb_catalog.dimension d ON (d.hypertable_id = h.id) -RIGHT JOIN _timescaledb_catalog.dimension_partition dp ON (dp.dimension_id = d.id) -ORDER BY dimension_id, range_start; -GRANT SELECT ON hypertable_partitions TO :ROLE_1; - --- Import testsupport.sql file to data nodes -\unset ECHO -\o /dev/null -\c :DATA_NODE_1 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_2 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_3 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\o -SET client_min_messages TO NOTICE; -\set ECHO all - -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; ---Ensure INSERTs use DataNodeDispatch. DataNodeCopy is tested later -SET timescaledb.enable_distributed_insert_with_copy=false; - --- Verify lack of tables -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; - -\set ON_ERROR_STOP 0 --- Test that one cannot directly create TimescaleDB foreign tables -CREATE FOREIGN TABLE foreign_table (time timestamptz, device int, temp float) SERVER :DATA_NODE_1; -\set ON_ERROR_STOP 1 - --- Create distributed hypertables. Add a trigger and primary key --- constraint to test how those work -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), color int, temp float, PRIMARY KEY (time,device)); - -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 1); - --- Increase the number of partitions. Expect warning since still too --- low. Dimension partitions should be updated to reflect new --- partitioning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; -SELECT * FROM set_number_partitions('disttable', 2); -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - --- Set number of partitions equal to the number of servers should not --- raise a warning. -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; -SELECT * FROM set_number_partitions('disttable', 3, 'device'); -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - --- Show the number of slices -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'disttable'; - --- This table tests both 1-dimensional tables and under-replication --- (replication_factor > num_data_nodes). -CREATE TABLE underreplicated(time timestamptz, device int, temp float); - -\set ON_ERROR_STOP 0 --- can't create an under-replicated hypertable -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); -\set ON_ERROR_STOP 1 - -RESET ROLE; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node(:'DATA_NODE_4', host => 'localhost', database => :'DATA_NODE_4'); -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_4 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; -SELECT * FROM create_hypertable('underreplicated', 'time', replication_factor => 4); - --- test that attaching a data node to an existing hypertable with --- repartition=>false does not change the number of partitions when --- number of partitions is greater than number of data nodes. -SELECT * FROM set_number_partitions('disttable', 8, 'device'); -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; -SELECT attach_data_node(:'DATA_NODE_4', 'disttable', repartition => false); -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - ---create new session to clear out connections -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_4', force => true, drop_database => true, repartition => false); -SET ROLE :ROLE_1; --- Deleting a data node should also not change the number of --- partitions with repartition=>false -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - --- reset to 3 partitions -SELECT * FROM set_number_partitions('disttable', 3, 'device'); -SELECT * FROM hypertable_partitions WHERE table_name = 'disttable'; - -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; - --- Create the trigger function on the data nodes: -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -DECLARE - cnt INTEGER; -BEGIN - SELECT count(*) INTO cnt FROM public.disttable; - RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %', - tg_when, tg_level, tg_op, cnt, tg_name; - - IF TG_OP = 'DELETE' THEN - RETURN OLD; - END IF; - RETURN NEW; -END -$BODY$; -$$); - -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 1,2,3; -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - --- The constraints, indexes, and triggers on the hypertable -SELECT * FROM test.show_constraints('disttable'); -SELECT * FROM test.show_indexes('disttable'); -SELECT * FROM test.show_triggers('disttable'); - --- Drop a column. This will make the attribute numbers of the --- hypertable's root relation differ from newly created chunks. It is --- a way to test that we properly handle attributed conversion between --- the root table and chunks -ALTER TABLE disttable DROP COLUMN color; - --- EXPLAIN some inserts to see what plans and explain output for --- remote inserts look like -EXPLAIN (COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - -EXPLAIN (VERBOSE, COSTS FALSE) -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1); - --- Create some chunks through insertion -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 09:21', 3, 2.2), - ('2017-01-01 08:11', 3, 2.3), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2017-01-02 09:01', 2, 1.4), - ('2017-01-02 08:21', 2, 1.5), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-02 09:01', 87, 1.4), - ('2018-07-02 09:21', 87, 1.8), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 06:21', 13, 1.5), - ('2018-07-01 07:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5), - ('2018-07-01 09:21', 90, 2.8), - ('2018-07-01 08:21', 29, 1.2); - --- EXPLAIN some updates/deletes to see what plans and explain output for --- remote operations look like -EXPLAIN (VERBOSE, COSTS FALSE) -UPDATE disttable SET temp = 3.7 WHERE device = 1; - -EXPLAIN (VERBOSE, COSTS FALSE) -DELETE FROM disttable WHERE device = 1; - --- Test distributed ANALYZE. --- - --- First show no statistics --- reltuples is initially -1 before any VACUUM/ANALYZE has been run on PG14 -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - -ANALYZE disttable; - --- Show updated statistics -SELECT relname, relkind, CASE WHEN reltuples > 0 THEN reltuples ELSE 0 END AS reltuples, relpages -FROM pg_class -WHERE oid = 'disttable'::regclass; - -SELECT relname, relkind, reltuples, relpages -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable')) ch -WHERE cl.oid = ch.chunk::regclass; - --- Test distributed VACUUM. --- -VACUUM (FULL, ANALYZE) disttable; -VACUUM FULL disttable; -VACUUM disttable; -\set ON_ERROR_STOP 0 --- VACUUM VERBOSE is not supported at the moment -VACUUM VERBOSE disttable; -\set ON_ERROR_STOP 1 - --- Test prepared statement -PREPARE dist_insert (timestamptz, int, float) AS -INSERT INTO disttable VALUES ($1, $2, $3); - -EXECUTE dist_insert ('2017-01-01 06:05', 1, 1.4); - --- Show chunks created -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); - --- Show that there are assigned node_chunk_id:s in chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - -SELECT * FROM hypertable_partitions; --- Show that chunks are created on data nodes and that each data node --- has their own unique slice in the space (device) dimension. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); - -SELECT node_name FROM timescaledb_information.data_nodes ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; - --- Show what some queries would look like on the frontend -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT * FROM disttable; - -SELECT * FROM disttable; - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -ORDER BY 1; - --- Execute some queries on the frontend and return the results -SELECT * FROM disttable; - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -GROUP BY 1, 2 -ORDER BY 1; - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM disttable -WHERE temp > 2 -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - --- Test AsyncAppend when using min/max aggregates -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - -SELECT max(temp) -FROM disttable; - --- Test turning off async append -SET timescaledb.enable_async_append = OFF; - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - -SET timescaledb.enable_async_append = ON; - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT min(temp), max(temp) -FROM disttable; - -SELECT min(temp), max(temp) -FROM disttable; - --- Test AsyncAppend when using window functions -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - -SELECT device, temp, avg(temp) OVER (PARTITION BY device) -FROM disttable -ORDER BY device, temp; - --- Test remote explain - --- Make sure that chunks_in function only expects one-dimensional integer arrays -\set ON_ERROR_STOP 0 -SELECT "time" FROM public.disttable WHERE _timescaledb_functions.chunks_in(public.disttable.*, ARRAY[[2], [1]]) -ORDER BY "time" DESC NULLS FIRST LIMIT 1; -\set ON_ERROR_STOP 1 - -SET timescaledb.enable_remote_explain = ON; - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when using max(time). -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(time) -FROM disttable; - -EXPLAIN (VERBOSE, COSTS FALSE) -SELECT max(temp) -FROM disttable; - --- Don't remote explain if there is no VERBOSE flag -EXPLAIN (COSTS FALSE) -SELECT max(temp) -FROM disttable; - --- Test additional EXPLAIN flags -EXPLAIN (ANALYZE, VERBOSE, COSTS FALSE, BUFFERS OFF, TIMING OFF, SUMMARY OFF) -SELECT max(temp) -FROM disttable; - --- The constraints, indexes, and triggers on foreign chunks. Only --- check constraints should recurse to foreign chunks (although they --- aren't enforced on a foreign table) -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - --- Check that the chunks are assigned data nodes -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - --- Adding a new trigger should not recurse to foreign chunks -CREATE TRIGGER _1_test_trigger_insert - AFTER INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; - --- Check that we can create indexes on distributed hypertables and --- that they don't recurse to foreign chunks -CREATE INDEX ON disttable (time, device); - -SELECT * FROM test.show_indexes('disttable'); -SELECT st."Child" as chunk_relid, test.show_indexes((st)."Child") -FROM test.show_subtables('disttable') st; - --- No index mappings should exist either -SELECT * FROM _timescaledb_catalog.chunk_index; - --- Check that creating columns work -ALTER TABLE disttable ADD COLUMN "Color" int; - -SELECT * FROM test.show_columns('disttable'); -SELECT st."Child" as chunk_relid, test.show_columns((st)."Child") -FROM test.show_subtables('disttable') st; - --- Adding a new unique constraint should not recurse to foreign --- chunks, but a check constraint should -ALTER TABLE disttable ADD CONSTRAINT disttable_color_unique UNIQUE (time, device, "Color"); -ALTER TABLE disttable ADD CONSTRAINT disttable_temp_non_negative CHECK (temp > 0.0); - -SELECT st."Child" as chunk_relid, test.show_constraints((st)."Child") -FROM test.show_subtables('disttable') st; - -SELECT cc.* -FROM (SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('disttable')) c, - _timescaledb_catalog.chunk_constraint cc -WHERE c.chunk_id = cc.chunk_id; - --- Show contents after re-adding column -SELECT * FROM disttable; - --- Test INSERTS with RETURNING. Since we previously dropped a column --- on the hypertable, this also tests that we handle conversion of the --- attribute numbers in the RETURNING clause, since they now differ --- between the hypertable root relation and the chunk currently --- RETURNING from. -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 4, 1, 9.8) -RETURNING time, "Color", temp; - -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-03 06:18', 9, 3, 8.7) -RETURNING 1; - --- On conflict -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-02 06:09', 6, 2, 10.5) -ON CONFLICT DO NOTHING; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable'); -$$); - --- Show new row and that conflicting row is not inserted -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); - - -\set ON_ERROR_STOP 0 - --- ON CONFLICT DO NOTHING only works when index inference is omitted -\set VERBOSITY default -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device) DO NOTHING; - -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT(time,device,"Color") DO NOTHING; - -INSERT INTO disttable -VALUES ('2017-09-02 06:09', 6) -ON CONFLICT ON CONSTRAINT disttable_color_unique DO NOTHING; -\set VERBOSITY terse - -SELECT * FROM disttable ORDER BY disttable; - --- ON CONFLICT only works with DO NOTHING for now -INSERT INTO disttable (time, device, "Color", temp) -VALUES ('2017-09-09 08:13', 7, 3, 27.5) -ON CONFLICT (time) DO UPDATE SET temp = 3.2; - --- Test that an INSERT that would create a chunk does not work on a --- data node -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2019-01-02 12:34', 1, 2, 9.3) -$$); -\set ON_ERROR_STOP 1 - --- However, INSERTs on a data node that does not create a chunk works. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - INSERT INTO disttable VALUES ('2017-09-03 06:09', 1, 2, 9.3) -$$); - --- Test updates -UPDATE disttable SET "Color" = 4 WHERE "Color" = 3; -SELECT * FROM disttable; - -WITH devices AS ( - SELECT DISTINCT device FROM disttable ORDER BY device -) -UPDATE disttable SET "Color" = 2 WHERE device = (SELECT device FROM devices LIMIT 1); - -\set ON_ERROR_STOP 0 --- Updates referencing non-existing column -UPDATE disttable SET device = 4 WHERE no_such_column = 2; -UPDATE disttable SET no_such_column = 4 WHERE device = 2; --- Update to system column -UPDATE disttable SET tableoid = 4 WHERE device = 2; -\set ON_ERROR_STOP 1 - --- Test deletes (no rows deleted) -DELETE FROM disttable WHERE device = 3 -RETURNING *; - -DELETE FROM disttable WHERE time IS NULL; - --- Test deletes (rows deleted) -DELETE FROM disttable WHERE device = 4 -RETURNING *; - --- Query to show that rows are deleted -SELECT * FROM disttable; - --- Ensure rows are deleted on the data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM disttable; -$$); - --- Test TRUNCATE -TRUNCATE disttable; - --- No data should remain -SELECT * FROM disttable; - --- Metadata and tables cleaned up -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM show_chunks('disttable'); - --- Also cleaned up remotely -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk; -SELECT * FROM show_chunks('disttable'); -SELECT * FROM disttable; -$$); - --- The hypertable view also shows no chunks and no data -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - --- Test underreplicated chunk warning -INSERT INTO underreplicated VALUES ('2017-01-01 06:01', 1, 1.1), - ('2017-01-02 07:01', 2, 3.5); - -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); - --- Show chunk data node mappings -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1,2,3; - --- Show that chunks are created on remote data nodes and that all --- data nodes/chunks have the same data due to replication -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('underreplicated'); -$$); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); - --- Test updates -UPDATE underreplicated SET temp = 2.0 WHERE device = 2 -RETURNING time, temp, device; - -SELECT * FROM underreplicated; - --- Show that all replica chunks are updated -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); - -DELETE FROM underreplicated WHERE device = 2 -RETURNING *; - --- Ensure deletes across all data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM underreplicated; -$$); - --- Test hypertable creation fails on distributed error -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, id int, cost float); -SELECT * FROM underreplicated; -$$); - -\set ON_ERROR_STOP 0 -CREATE TABLE remotetable(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_hypertable('remotetable', 'time', replication_factor => 1); - --- Test distributed_hypertable creation fails with replication factor 0 -CREATE TABLE remotetable2(time timestamptz PRIMARY KEY, device int CHECK (device > 0), color int, temp float); -SELECT * FROM create_distributed_hypertable('remotetable2', 'time', replication_factor => 0); -\set ON_ERROR_STOP 1 - -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - --- Test distributed hypertable creation with many parameters -\c :TEST_DBNAME :ROLE_SUPERUSER - ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; -CREATE SCHEMA "T3sTSch"; -CREATE SCHEMA "Table\\Schema"; -CREATE SCHEMA "single'schema"; -GRANT ALL ON SCHEMA "T3sTSch" TO :ROLE_1; -GRANT ALL ON SCHEMA "Table\\Schema" TO :ROLE_1; -GRANT ALL ON SCHEMA "single'schema" TO :ROLE_1; -SET ROLE :ROLE_1; -CREATE TABLE "Table\\Schema"."Param_Table"("time Col %#^#@$#" timestamptz, __region text, reading float); -SELECT * FROM create_distributed_hypertable('"Table\\Schema"."Param_Table"', 'time Col %#^#@$#', partitioning_column => '__region', -associated_schema_name => 'T3sTSch', associated_table_prefix => 'test*pre_', chunk_time_interval => interval '1 week', -create_default_indexes => FALSE, if_not_exists => TRUE, replication_factor => 2, -data_nodes => ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); - --- Test detach and attach data node -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, drop_remote_data => true); - --- Test attach_data_node. First show dimensions and currently attached --- servers. The number of slices in the space dimension should equal --- the number of servers since we didn't explicitly specify --- number_partitions -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - -SELECT * FROM attach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"'); - --- Show updated metadata after attach -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - -SELECT h.table_name, hdn.node_name -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.hypertable_data_node hdn -WHERE h.id = hdn.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2; - --- Attach another data node but do not auto-repartition, i.e., --- increase the number of slices. -SELECT * FROM attach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', repartition => false); - --- Number of slices should not be increased -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table' -ORDER BY 1, 2, 3; - --- Manually increase the number of partitions -SELECT * FROM set_number_partitions('"Table\\Schema"."Param_Table"', 4); - --- Verify hypertables on all data nodes -SELECT * FROM _timescaledb_catalog.hypertable; -SELECT * FROM _timescaledb_catalog.dimension; -SELECT * FROM test.show_triggers('"Table\\Schema"."Param_Table"'); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.hypertable; -SELECT * FROM _timescaledb_catalog.dimension; -SELECT t.tgname, t.tgtype, t.tgfoid::regproc -FROM pg_trigger t, pg_class c WHERE c.relname = 'Param_Table' AND t.tgrelid = c.oid; -$$); - --- Verify that repartitioning works as expected on detach_data_node -SELECT * FROM detach_data_node(:'DATA_NODE_1', '"Table\\Schema"."Param_Table"', repartition => true); -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; -SELECT * FROM detach_data_node(:'DATA_NODE_2', '"Table\\Schema"."Param_Table"', force => true, repartition => false); -SELECT h.table_name, d.column_name, d.num_slices -FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id -AND h.table_name = 'Param_Table'; - --- Test multi-dimensional hypertable. The add_dimension() command --- should be propagated to backends. -CREATE TABLE dimented_table (time timestamptz, column1 int, column2 timestamptz, column3 int); -SELECT * FROM create_distributed_hypertable('dimented_table', 'time', partitioning_column => 'column1', number_partitions => 4, replication_factor => 1, data_nodes => ARRAY[:'DATA_NODE_1']); --- Create one chunk to block add_dimension -INSERT INTO dimented_table VALUES('2017-01-01 06:01', 1, '2017-01-01 08:01', 1); - -CREATE VIEW dimented_table_slices AS -SELECT c.id AS chunk_id, c.hypertable_id, ds.dimension_id, cc.dimension_slice_id, c.schema_name AS - chunk_schema, c.table_name AS chunk_table, ds.range_start, ds.range_end -FROM _timescaledb_catalog.chunk c -INNER JOIN _timescaledb_catalog.hypertable h ON (c.hypertable_id = h.id) -INNER JOIN _timescaledb_catalog.dimension td ON (h.id = td.hypertable_id) -INNER JOIN _timescaledb_catalog.dimension_slice ds ON (ds.dimension_id = td.id) -INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.dimension_slice_id = ds.id AND cc.chunk_id = c.id) -WHERE h.table_name = 'dimented_table' -ORDER BY c.id, ds.dimension_id; - -SELECT * FROM dimented_table_slices; - --- add_dimension() with existing data -SELECT * FROM add_dimension('dimented_table', 'column2', chunk_time_interval => interval '1 week'); -SELECT * FROM dimented_table_slices; - -SELECT * FROM add_dimension('dimented_table', 'column3', 4, partitioning_func => '_timescaledb_functions.get_partition_for_key'); -SELECT * FROM dimented_table_slices; -SELECT * FROM dimented_table ORDER BY time; - -SELECT * FROM _timescaledb_catalog.dimension; -SELECT * FROM attach_data_node(:'DATA_NODE_2', 'dimented_table'); - -SELECT * FROM _timescaledb_catalog.dimension; - --- ensure data node has new dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM _timescaledb_catalog.dimension; -$$); - ---test per-data node queries --- Create some chunks through insertion -CREATE TABLE disttable_replicated(time timestamptz PRIMARY KEY, device int CHECK (device > 0), temp float, "Color" int); -SELECT * FROM create_hypertable('disttable_replicated', 'time', replication_factor => 2); -INSERT INTO disttable_replicated VALUES - ('2017-01-01 06:01', 1, 1.1, 1), - ('2017-01-01 08:01', 1, 1.2, 2), - ('2018-01-02 08:01', 2, 1.3, 3), - ('2019-01-01 09:11', 3, 2.1, 4), - ('2020-01-01 06:01', 5, 1.1, 10), - ('2020-01-01 08:01', 6, 1.2, 11), - ('2021-01-02 08:01', 7, 1.3, 12), - ('2022-01-01 09:11', 8, 2.1, 13); - -SELECT * FROM disttable_replicated; - -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; - ---guc disables the optimization -SET timescaledb.enable_per_data_node_queries = FALSE; -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated; -SET timescaledb.enable_per_data_node_queries = TRUE; - ---test WHERE clause -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0; - ---test OR -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE temp > 2.0 or "Color" = 11; - ---test some chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2018-01-01 09:11'; - ---test all chunks excluded -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -SELECT * FROM disttable_replicated WHERE time < '2002-01-01 09:11'; - ---test cte -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH cte AS ( - SELECT * FROM disttable_replicated -) -SELECT * FROM cte; - ---queries that involve updates/inserts are not optimized -EXPLAIN (VERBOSE, ANALYZE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE) -WITH devices AS ( - SELECT DISTINCT device FROM disttable_replicated ORDER BY device -) -UPDATE disttable_replicated SET device = 2 WHERE device = (SELECT device FROM devices LIMIT 1); - - --- Test inserts with smaller batch size and more tuples to reach full --- batch -SET timescaledb.max_insert_batch_size=4; - -CREATE TABLE twodim (time timestamptz DEFAULT '2019-02-10 10:11', "Color" int DEFAULT 11 CHECK ("Color" > 0), temp float DEFAULT 22.1); --- Create a replicated table to ensure we handle that case correctly --- with batching -SELECT * FROM create_hypertable('twodim', 'time', 'Color', 3, replication_factor => 2, data_nodes => ARRAY[:'DATA_NODE_1',:'DATA_NODE_2',:'DATA_NODE_3']); - -SELECT * FROM twodim -ORDER BY time; - --- INSERT enough data to stretch across multiple batches per --- data node. Also return a system column. Although we write tuples to --- multiple data nodes, the returned tuple should only be the ones in the --- original insert statement (without the replica tuples). -WITH result AS ( - INSERT INTO twodim VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1) - RETURNING tableoid = 'twodim'::regclass AS is_tableoid, time, temp, "Color" -) SELECT * FROM result ORDER BY time; - --- Test insert with default values and a batch size of 1. -SET timescaledb.max_insert_batch_size=1; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim DEFAULT VALUES; -INSERT INTO twodim DEFAULT VALUES; - --- Reset the batch size -SET timescaledb.max_insert_batch_size=4; - --- Constraint violation error check --- --- Execute and filter mentioned data node name in the error message. -\set ON_ERROR_STOP 0 -SELECT test.execute_sql_and_filter_data_node_name_on_error($$ INSERT INTO twodim VALUES ('2019-02-10 17:54', 0, 10.2) $$, :'TEST_DBNAME'); -\set ON_ERROR_STOP 1 - --- Disable batching, reverting to FDW tuple-by-tuple inserts. --- First EXPLAIN with batching turned on. -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - -SET timescaledb.max_insert_batch_size=0; - --- Compare without batching -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - --- Insert without batching -INSERT INTO twodim VALUES - ('2019-02-10 16:23', 5, 7.1), - ('2019-02-10 17:11', 7, 3.2); - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when multiple dimensions are involved. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT * FROM twodim -ORDER BY time; -SET timescaledb.enable_remote_explain = OFF; - --- Check results -SELECT * FROM twodim -ORDER BY time; - -SELECT count(*) FROM twodim; - --- Show distribution across data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT * FROM twodim -ORDER BY time; -SELECT count(*) FROM twodim; -$$); - --- Distributed table with custom type that has no binary output -CREATE TABLE disttable_with_ct(time timestamptz, txn_id rxid, val float, info text); -SELECT * FROM create_hypertable('disttable_with_ct', 'time', replication_factor => 2); - --- Insert data with custom type -INSERT INTO disttable_with_ct VALUES - ('2019-01-01 01:01', 'ts-1-10-20-30', 1.1, 'a'), - ('2019-01-01 01:02', 'ts-1-11-20-30', 2.0, repeat('abc', 1000000)); -- TOAST - --- Test queries on distributed table with custom type -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - -SET timescaledb.enable_connection_binary_data=false; - -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; - --- Test DELETE with replication -DELETE FROM disttable_with_ct WHERE info = 'a'; --- Check if row is gone -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; --- Connect to data nodes to see if data is gone - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT time, txn_id, val, substring(info for 20) FROM disttable_with_ct; -$$); - --- Test single quote in names -SET SCHEMA 'single''schema'; -CREATE TABLE "disttable'quote"(time timestamptz, "device'quote" int, val float, info text); -SELECT public.create_distributed_hypertable( - 'disttable''quote', 'time', 'device''quote', data_nodes => ARRAY[:'DATA_NODE_1'] -); - -SET SCHEMA 'public'; -CREATE TABLE disttable_drop_chunks(time timestamptz, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('disttable_drop_chunks', 'time', 'device', number_partitions => 3, replication_factor => 2); - -INSERT INTO disttable_drop_chunks VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 2, 1.3), - ('2018-07-02 08:01', 87, 1.6), - ('2018-07-01 06:01', 13, 1.4), - ('2018-07-01 09:11', 90, 2.7), - ('2018-07-01 08:01', 29, 1.5); - --- Show chunks on access node -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - --- Show chunks on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); - -SELECT * FROM drop_chunks('disttable_drop_chunks', older_than => '2018-01-01'::timestamptz); - -SELECT * FROM disttable_drop_chunks; - -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT (_timescaledb_functions.show_chunk(show_chunks)).* -FROM show_chunks('disttable_drop_chunks'); -$$); - --- test passing newer_than as interval -SELECT * FROM drop_chunks('disttable_drop_chunks', newer_than => interval '10 years'); -SELECT * FROM disttable_drop_chunks; - -CREATE TABLE "weird nAme\\#^."(time bigint, device int CHECK (device > 0), color int, PRIMARY KEY (time,device)); -SELECT * FROM create_distributed_hypertable('"weird nAme\\#^."', 'time', 'device', 3, chunk_time_interval => 100, replication_factor => 2); - -INSERT INTO "weird nAme\\#^." VALUES - (300, 1, 1.1), - (400, 3, 2.1), - (350, 1, 1.2); - -SELECT * FROM "weird nAme\\#^."; --- drop chunks using bigint as time -SELECT * FROM drop_chunks('"weird nAme\\#^."', older_than => 1000); -SELECT * FROM "weird nAme\\#^."; - ------------------------------------------------------------------------------------------ --- Test that settings on hypertables are distributed to data nodes ------------------------------------------------------------------------------------------ - -DROP TABLE disttable CASCADE; -CREATE TABLE disttable (time bigint, device int, temp float); -SELECT create_distributed_hypertable('disttable', 'time', chunk_time_interval => 1000000::bigint); - --- Show the dimension configuration on data nodes -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); --- Test adding a space dimension. Should apply to data nodes as --- well. We're setting num_partitions lower than the number of servers --- and expect a warning. -SELECT * FROM add_dimension('disttable', 'device', 1, partitioning_func => '_timescaledb_functions.get_partition_hash'); -CREATE INDEX disttable_device_time_idx ON disttable (device, time); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); - --- Show that changing dimension settings apply to data nodes -SELECT * FROM set_chunk_time_interval('disttable', 2000000000::bigint); -SELECT * FROM set_number_partitions('disttable', 3); - -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT'; -CALL distributed_exec($$ -CREATE OR REPLACE FUNCTION dummy_now() RETURNS BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 2::BIGINT' -$$); - -SELECT * FROM set_integer_now_func('disttable', 'dummy_now'); - --- Show changes to dimensions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT d.* FROM _timescaledb_catalog.hypertable h, _timescaledb_catalog.dimension d -WHERE h.id = d.hypertable_id AND h.table_name = 'disttable'; -$$); - --- Tests for using tablespaces with distributed hypertables -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; ---Ensure INSERTs use DataNodeDispatch. -SET timescaledb.enable_distributed_insert_with_copy=false; - -CREATE TABLESPACE :TABLESPACE_1 OWNER :ROLE_1 LOCATION :'spc1path'; -CREATE TABLESPACE :TABLESPACE_2 OWNER :ROLE_1 LOCATION :'spc2path'; -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_1', 'disttable'); -SELECT detach_tablespace(:'TABLESPACE_1', 'disttable'); -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable'); - --- Continue to use previously attached tablespace, but block attach/detach -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_distributed_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint); - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); - -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -\set ON_ERROR_STOP 1 -SELECT detach_tablespaces('disttable2'); - -SELECT * FROM show_tablespaces('disttable2'); - --- Ensure tablespace API works for data nodes -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT detach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec(format($$ -SELECT attach_tablespace(%L, 'disttable2'); -$$, :'TABLESPACE_2')); -CALL distributed_exec($$ -SELECT detach_tablespaces('disttable2'); -$$); -DROP TABLE disttable2; - -CREATE TABLE disttable2(time timestamptz, device int, temp float) TABLESPACE :TABLESPACE_1; -SELECT create_hypertable('disttable2', 'time', chunk_time_interval => 1000000::bigint, replication_factor => 1); - --- Ensure that table is created on the data nodes without a tablespace -CALL distributed_exec($$ -SELECT * FROM show_tablespaces('disttable2'); -$$); - -INSERT INTO disttable2 VALUES ('2017-01-01 06:01', 1, 1.1); -SELECT * FROM show_chunks('disttable2'); - --- Ensure tablespace oid is set to 0 for a foreign table -SELECT reltablespace -FROM pg_class cl, (SELECT show_chunks AS chunk FROM show_chunks('disttable2')) ch -WHERE cl.oid = ch.chunk::regclass; - -\set ON_ERROR_STOP 0 -SELECT attach_tablespace(:'TABLESPACE_2', 'disttable2'); -SELECT detach_tablespace(:'TABLESPACE_2', 'disttable2'); -\set ON_ERROR_STOP 1 - -SELECT * FROM show_tablespaces('disttable2'); -DROP TABLE disttable2; - -DROP TABLESPACE :TABLESPACE_1; -DROP TABLESPACE :TABLESPACE_2; - --- Make sure table qualified name is used in chunks_in function. Otherwise having a table name same as a column name might yield an error -CREATE TABLE dist_device(time timestamptz, dist_device int, temp float); -SELECT * FROM create_distributed_hypertable('dist_device', 'time'); - -INSERT INTO dist_device VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 3, 2.1), - ('2017-01-01 08:01', 1, 1.2); - -EXPLAIN (VERBOSE, COSTS OFF) -SELECT * FROM dist_device; - --- Check that datanodes use ChunkAppend plans with chunks_in function in the --- "Remote SQL" when only time partitioning is being used. -SET timescaledb.enable_remote_explain = ON; -EXPLAIN (VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) -SELECT "time", dist_device, temp FROM public.dist_device ORDER BY "time" ASC NULLS LAST; - -SELECT * FROM dist_device; - --- Test estimating relation size without stats -CREATE TABLE hyper_estimate(time timestamptz, device int, temp float); -SELECT * FROM create_distributed_hypertable('hyper_estimate', 'time', 'device', number_partitions => 3, replication_factor => 1, chunk_time_interval => INTERVAL '7 days'); - --- This will enable us to more easily see estimates per chunk -SET timescaledb.enable_per_data_node_queries = false; - --- Estimating chunk progress uses current timestamp so we override it for test purposes -SELECT test.tsl_override_current_timestamptz('2017-11-11 00:00'::timestamptz); - --- Test estimates when backfilling. 3 chunks should be historical and 3 should be considered current when estimating. --- Note that estimate numbers are way off since we are using shared buffer size as starting point. This will not be --- an issue in 'production' like env since chunk size should be similar to shared buffer size. -INSERT INTO hyper_estimate VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); - --- This will calculate the stats -ANALYZE hyper_estimate; - -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - --- Let's insert data into a new chunk. This will result in chunk creation. -INSERT INTO hyper_estimate VALUES ('2019-11-11 06:01', 1, 1.1); - --- We have stats for previous chunks so we can interpolate number of rows for the new chunk -EXPLAIN (COSTS ON) -SELECT * -FROM hyper_estimate; - -CREATE TABLE devices ( - device_id INTEGER PRIMARY KEY, - device_name VARCHAR(10) -); - -CALL distributed_exec($$ - CREATE TABLE devices(device_id INTEGER PRIMARY KEY, device_name VARCHAR(10)) -$$); - -INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765'); - -CALL distributed_exec($$ - INSERT INTO devices VALUES - (1, 'A001'), (2, 'B015'), (3, 'D821'), (4, 'C561'), (5, 'D765') -$$); - -CREATE TABLE hyper ( - time TIMESTAMPTZ NOT NULL, - device INTEGER REFERENCES devices(device_id), - temp FLOAT -); - -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours' -); - --- Inserting some values should succeed. -INSERT INTO hyper VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 09:11', 1, 2.1), - ('2017-01-01 08:01', 1, 1.2), - ('2017-01-02 08:01', 1, 1.3), - ('2017-01-02 08:01', 2, 1.6), - ('2017-01-02 06:01', 2, 1.4), - ('2017-01-03 01:01', 3, 2), - ('2017-01-03 01:16', 3, 3), - ('2017-01-03 01:17', 3, 4), - ('2018-01-13 01:01', 1, 2), - ('2018-01-13 01:10', 1, 0.4), - ('2018-01-13 02:10', 2, 1.4), - ('2018-01-13 05:01', 2, 2), - ('2018-01-13 05:50', 2, 4), - ('2018-01-13 16:01', 3, 2); - -SELECT time_bucket('3 hours', time) AS time, device, avg(temp) AS avg_temp -FROM hyper -GROUP BY 1, 2 -HAVING avg(temp) > 1.2 -ORDER BY 1; - --- Add some devices on the access node only. Inserts should then fail. -INSERT INTO devices VALUES (6, 'E999'); - -\set ON_ERROR_STOP 0 -INSERT INTO hyper VALUES ('2017-01-01 06:01', 6, 1.1); -\set ON_ERROR_STOP 1 - --- Test alter replication factor with data - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); - --- Dimension partitions should be updated to account for replication --- to additional data nodes -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; -SELECT * FROM set_replication_factor('hyper', 3); -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - -INSERT INTO hyper VALUES ('2017-01-02 07:11', 1, 1.7); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); - -INSERT INTO hyper VALUES ('2017-02-01 06:01', 1, 5.1); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); - -SELECT * FROM set_replication_factor('hyper', 2); -SELECT * FROM hypertable_partitions WHERE table_name = 'hyper'; - -INSERT INTO hyper VALUES ('2017-03-01 06:01', 1, 15.1); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); - -SELECT * FROM set_replication_factor('hyper', replication_factor => 2); - -INSERT INTO hyper VALUES ('2017-04-01 06:01', 2, 45.1); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT (_timescaledb_functions.show_chunk(show_chunks)).* - FROM show_chunks('hyper'); -$$); - -\set ON_ERROR_STOP 0 -SELECT * FROM set_replication_factor('hyper', replication_factor => 4); -\set ON_ERROR_STOP 1 - -DROP TABLE hyper; -CALL distributed_exec($$ - DROP TABLE devices; -$$); -DROP TABLE devices; - --- Test storage options are distributed to data nodes --- --- Make sure that options used during CREATE TABLE WITH and CREATE INDEX WITH --- are properly distributed. --- -CREATE TABLE disttable_with_relopts_1(time timestamptz NOT NULL, device int) WITH (fillfactor=10); -CREATE TABLE disttable_with_relopts_2(time timestamptz NOT NULL, device int) WITH (fillfactor=10, parallel_workers=1); -CREATE TABLE disttable_with_relopts_3(time timestamptz NOT NULL, device int); -CREATE INDEX disttable_with_relopts_3_idx ON disttable_with_relopts_3(device) WITH (fillfactor=20); - -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_1', 'time'); -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_2', 'time'); -SELECT * FROM create_distributed_hypertable('disttable_with_relopts_3', 'time'); - -INSERT INTO disttable_with_relopts_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); - -INSERT INTO disttable_with_relopts_2 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3' ORDER BY relname; -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; - --- Ensure reloptions are not set for distributed hypertable chunks on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) -ORDER BY relname; - --- Ensure parent tables has proper storage options -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; -$$); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_2' ORDER BY relname; -$$); - --- Ensure index has proper storage options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_3_idx' ORDER BY relname; -$$); - --- Make sure chunks derive parent reloptions -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_2')) - ORDER BY relname; -$$); - --- ALTER TABLE SET/RESET support for distributed hypertable --- --- SET -ALTER TABLE disttable_with_relopts_1 SET (fillfactor=40); - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); - --- RESET -ALTER TABLE disttable_with_relopts_1 RESET (fillfactor); - -SELECT relname, reloptions FROM pg_class WHERE relname = 'disttable_with_relopts_1' ORDER BY relname; - --- Ensure chunks are not affected on the AN -SELECT relname, reloptions FROM pg_class WHERE relname IN -(SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) -ORDER BY relname; - --- Ensure data node chunks has proper options set -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT relname, reloptions FROM pg_class WHERE relname IN - (SELECT (_timescaledb_functions.show_chunk(show_chunks)).table_name FROM show_chunks('disttable_with_relopts_1')) - ORDER BY relname; -$$); - -DROP TABLE disttable_with_relopts_1; -DROP TABLE disttable_with_relopts_2; -DROP TABLE disttable_with_relopts_3; - --- Test SERIAL type column support for distributed hypertables --- -CREATE TABLE disttable_serial(time timestamptz NOT NULL, device int, id1 SERIAL, id2 SMALLSERIAL, id3 BIGSERIAL); -SELECT create_distributed_hypertable('disttable_serial', 'time', 'device'); - --- Show created columns (AN and DN tables must be exact) -SELECT * FROM test.show_columns('disttable_serial'); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * FROM test.show_columns('disttable_serial'); -$$); - --- Ensure DEFAULT expression is applied on the AN only -SELECT column_name, column_default -FROM information_schema.columns -WHERE table_name = 'disttable_serial'; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT column_name, column_default - FROM information_schema.columns - WHERE table_name = 'disttable_serial'; -$$); - --- Ensure sequences were created on the AN only -INSERT INTO disttable_serial VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); -SELECT currval('disttable_serial_id1_seq'::regclass), - currval('disttable_serial_id2_seq'::regclass), - currval('disttable_serial_id3_seq'::regclass); -\set ON_ERROR_STOP 0 -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ - SELECT currval('disttable_serial_id1_seq'::regclass); -$$); -\set ON_ERROR_STOP 1 - --- Verify that the data is getting spread over multiple data nodes with the --- serial values being set correctly -SELECT * from disttable_serial ORDER BY id1; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - SELECT * from disttable_serial ORDER BY id1; -$$); - -DROP TABLE disttable_serial; - --- Test insert batching case which will hit the limit of arguments for --- prepared statements (65k). --- --- Issue: #1702 --- distributed hypertable insert fails when # of columns are more than 65 --- - --- Use default value -SET timescaledb.max_insert_batch_size TO 1000; - -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int , - dummy6 int , - dummy7 int , - dummy8 int , - dummy9 int , - dummy10 int , - dummy11 int , - dummy12 int , - dummy13 int , - dummy14 int , - dummy15 int , - dummy16 int , - dummy17 int , - dummy18 int , - dummy19 int , - dummy20 int , - dummy21 int , - dummy22 int , - dummy23 int , - dummy24 int , - dummy25 int , - dummy26 int , - dummy27 int , - dummy28 int , - dummy29 int , - dummy30 int , - dummy31 int , - dummy32 int , - dummy33 int , - dummy34 int , - dummy35 int , - dummy36 int , - dummy37 int , - dummy38 int , - dummy39 int , - dummy40 int , - dummy41 int , - dummy42 int , - dummy43 int , - dummy44 int , - dummy45 int , - dummy46 int , - dummy47 int , - dummy48 int , - dummy49 int , - dummy50 int , - dummy51 int , - dummy52 int , - dummy53 int , - dummy54 int , - dummy55 int , - dummy56 int , - dummy57 int , - dummy58 int , - dummy59 int , - dummy60 int , - dummy61 int , - dummy62 int , - dummy63 int , - dummy64 int , - dummy65 int , - dummy66 int , - dummy67 int , - dummy68 int , - dummy69 int , - dummy70 int , - dummy71 int -); - -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); - --- Original issue case --- --- Expect batch size to be lower than defined max_insert_batch_size --- -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); -INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; -INSERT INTO test_1702(id, time) SELECT generate_series(2, 1500), current_timestamp; -SELECT count(*) from test_1702; - -DROP TABLE test_1702; - --- --- Expect batch size to be similair to max_insert_batch_size --- -CREATE TABLE test_1702 ( - id varchar(100) NOT NULL, - time timestamp NOT NULL, - dummy1 int , - dummy2 int , - dummy4 int , - dummy5 int - ); - -SELECT create_distributed_hypertable('test_1702', 'time', 'id'); - -EXPLAIN (COSTS OFF) INSERT INTO test_1702(id, time) VALUES('1', current_timestamp); - -DROP TABLE test_1702; - --- --- Test that creating a hypertable with a space dimension and --- if_not_exists works as expected, that is, the second call does not --- generate an error (and does not crash). --- - -CREATE TABLE whatever ( - timestamp TIMESTAMPTZ NOT NULL, - user_id INT NOT NULL, - data JSONB -); - -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); --- Check the hypertable sequence before and after call to ensure that --- the hypertable sequence was not increased with the second call. -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; -SELECT * FROM create_distributed_hypertable('whatever', 'timestamp', 'user_id', - if_not_exists => true, chunk_time_interval => INTERVAL '1 day'); -SELECT last_value FROM _timescaledb_catalog.hypertable_id_seq; - --- Test that creating a distributed hypertable from a table with data --- fails, and that migrate_data blocked. - -CREATE TABLE dist_hypertable_1 ( - time TIMESTAMPTZ NOT NULL, - device INTEGER, - temp FLOAT -); - -INSERT INTO dist_hypertable_1 VALUES - ('2017-01-01 06:01', 1), - ('2017-01-01 09:11', 3), - ('2017-01-01 08:01', 1), - ('2017-01-02 08:01', 2), - ('2018-07-02 08:01', 87); - - -\set ON_ERROR_STOP 0 -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => FALSE); -SELECT * FROM create_distributed_hypertable('dist_hypertable_1', 'time', 'device', 3, - migrate_data => TRUE); -\set ON_ERROR_STOP 1 - --- Test creating index with transaction per chunk on a distributed hypertable --- -DROP TABLE disttable; - -CREATE TABLE disttable( - time timestamptz NOT NULL, - device int, - value float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, 1.2), - ('2017-01-01 09:11', 3, 4.3), - ('2017-01-01 08:01', 1, 7.3), - ('2017-01-02 08:01', 2, 0.23), - ('2018-07-02 08:01', 87, 0.0), - ('2018-07-01 06:01', 13, 3.1), - ('2018-07-01 09:11', 90, 10303.12), - ('2018-07-01 08:01', 29, 64); -\set ON_ERROR_STOP 0 -CREATE INDEX disttable_time_device_idx ON disttable (time, device) WITH (timescaledb.transaction_per_chunk); -\set ON_ERROR_STOP 1 - --- Test using system columns with distributed hypertable --- -CREATE TABLE dist_syscol(time timestamptz NOT NULL, color int, temp float); -SELECT * FROM create_distributed_hypertable('dist_syscol', 'time', 'color'); - -INSERT INTO dist_syscol VALUES - ('2017-02-01 06:01', 1, 1.1), - ('2017-02-01 08:01', 1, 1.2), - ('2018-02-02 08:01', 2, 1.3), - ('2019-02-01 09:11', 3, 2.1), - ('2019-02-02 09:11', 3, 2.1), - ('2019-02-02 10:01', 5, 1.2), - ('2019-02-03 11:11', 6, 3.5), - ('2019-02-04 08:21', 4, 6.6), - ('2019-02-04 10:11', 7, 7.4), - ('2019-02-04 12:11', 8, 2.1), - ('2019-02-05 13:31', 8, 6.3), - ('2019-02-06 02:11', 5, 1.8), - ('2019-02-06 01:13', 7, 7.9), - ('2019-02-06 19:24', 9, 5.9), - ('2019-02-07 18:44', 5, 9.7), - ('2019-02-07 20:24', 6, NULL), - ('2019-02-07 09:33', 7, 9.5), - ('2019-02-08 08:54', 1, 7.3), - ('2019-02-08 18:14', 4, 8.2), - ('2019-02-09 19:23', 8, 9.1); - --- Return chunk table as a source -SET timescaledb.enable_per_data_node_queries = false; -SELECT tableoid::regclass, * FROM dist_syscol; - --- Produce an error -SET timescaledb.enable_per_data_node_queries = true; -\set ON_ERROR_STOP 0 -SELECT tableoid::regclass, * FROM dist_syscol; -\set ON_ERROR_STOP 1 - ------------------------ --- Test DataNodeCopy -- ------------------------ -SET timescaledb.enable_distributed_insert_with_copy=true; -DROP TABLE disttable; - --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with DataNodeCopy -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -CREATE TYPE highlow AS (high int, low int); -CALL distributed_exec($$ CREATE TYPE highlow AS (high int, low int) $$); -ALTER TABLE datatable ADD COLUMN minmaxes highlow[]; -INSERT INTO datatable (id, time, device, temp_c, minmaxes) VALUES - (1, '2017-01-01 06:01', 1, 1.2, ARRAY[(1,2)::highlow]), - (2, '2017-01-01 09:11', 3, 4.3, ARRAY[(2,3)::highlow]), - (3, '2017-01-01 08:01', 1, 7.3, ARRAY[(4,5)::highlow]), - (4, '2017-01-02 08:01', 2, 0.23, ARRAY[(6,7)::highlow]), - (5, '2018-07-02 08:01', 87, 0.0, ARRAY[(8,9)::highlow]), - (6, '2018-07-01 06:01', 13, 3.1, ARRAY[(10,11)::highlow]), - (7, '2018-07-01 09:11', 90, 10303.12, ARRAY[(12,13)::highlow]), - (8, '2018-07-01 08:01', 29, 64, ARRAY[(14,15)::highlow]); - --- Show that DataNodeCopy is used instead of DataNodeDispatch. Should --- default to FORMAT binary in the remote SQL. Add RETURNING to show --- that it works. -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - --- Perform the actual insert -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable -RETURNING *; - --- Show that the data was added: -SELECT * FROM disttable ORDER BY 1; -SELECT count(*) FROM disttable; - --- Add an array of a composite type to check that DataNodeCopy --- switches to text format if we use a table with an array of a custom --- type. There should be no "FORMAT binary" in the remote explain. -ALTER TABLE disttable ADD COLUMN minmaxes highlow[]; - -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; -INSERT INTO disttable (time, device, temp_c, minmaxes) -SELECT time, device, temp_c, minmaxes FROM datatable; - --- Should have double amount of rows compared to before and half of --- them values in the new column. Note, must use TEXT format on the --- connection to make query work with custom type array. -SET timescaledb.enable_connection_binary_data=false; -SELECT * FROM disttable ORDER BY 1; -SELECT count(*) FROM disttable; - --- Binary format should lead to data incompatibility in PG 13 and earlier, --- because the highlow data type has different oids on data and access nodes. --- Use this to test the deserialization error reporting. Newer PG version --- ignore this oid mismatch for non-builtin types. -SET timescaledb.enable_connection_binary_data=true; -\set ON_ERROR_STOP 0 -SET timescaledb.remote_data_fetcher = 'copy'; -SELECT * FROM disttable ORDER BY 1; - -SET timescaledb.remote_data_fetcher = 'cursor'; -SELECT * FROM disttable ORDER BY 1; -\set ON_ERROR_STOP 1 - -RESET timescaledb.remote_data_fetcher; - --- Show that DataNodeCopy is NOT used when source hypertable and target hypertable --- of the SELECT are both distributed. Try subselects with LIMIT, RETURNING and --- different distributed hypertable as source -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable LIMIT 1; -EXPLAIN (COSTS OFF) -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable RETURNING *; -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM disttable; -INSERT INTO disttable (time, device, temp_c) -SELECT * FROM hyper_estimate LIMIT 2; -SELECT count(*) FROM disttable; - --- REMOVE a column on data nodes to check how errors are handled: -CALL distributed_exec($$ ALTER TABLE disttable DROP COLUMN minmaxes $$); - -\set ON_ERROR_STOP 0 -INSERT INTO disttable SELECT * FROM datatable; -\set ON_ERROR_STOP 1 - -DROP TABLE disttable; - --- Create a new table access method by reusing heap handler -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -CREATE ACCESS METHOD test_am TYPE TABLE HANDLER heap_tableam_handler; -$$); - --- Create distributed hypertable using non-default access method -CREATE TABLE disttable(time timestamptz NOT NULL, device int, temp_c float, temp_f float GENERATED ALWAYS AS (temp_c * 9 / 5 + 32) STORED) USING test_am; -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device', 3); - --- Make sure that distributed hypertable created on data nodes is --- using the correct table access method -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ - -SELECT amname AS hypertable_amname -FROM pg_class cl, pg_am am -WHERE cl.oid = 'disttable'::regclass -AND cl.relam = am.oid; -$$); - --- Check that basic operations are working as expected -INSERT INTO disttable VALUES - ('2017-01-01 06:01', 1, -10.0), - ('2017-01-01 09:11', 3, -5.0), - ('2017-01-01 08:01', 1, 1.0), - ('2017-01-02 08:01', 2, 5.0), - ('2018-07-02 08:01', 87, 10.0), - ('2018-07-01 06:01', 13, 15.0), - ('2018-07-01 09:11', 90, 20.0), - ('2018-07-01 08:01', 29, 24.0); - -SELECT * FROM disttable ORDER BY time; - --- Show that GENERATED columns work for INSERT with RETURNING clause --- (should use DataNodeCopy) -TRUNCATE disttable; -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; -INSERT INTO disttable VALUES ('2017-08-01 06:01', 1, 35.0) RETURNING *; - --- Same values returned with SELECT: -SELECT * FROM disttable ORDER BY 1; - -UPDATE disttable SET temp_c=40.0 WHERE device=1; -SELECT * FROM disttable ORDER BY 1; - --- Insert another value -INSERT INTO disttable VALUES ('2017-09-01 06:01', 2, 30.0); -SELECT * FROM disttable ORDER BY 1; --- Delete a value based on the generated column -DELETE FROM disttable WHERE temp_f=104; - -SELECT * FROM disttable ORDER BY 1; - --- Test also with DataNodeDispatch -TRUNCATE disttable; -SET timescaledb.enable_distributed_insert_with_copy=false; - -EXPLAIN VERBOSE -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; -INSERT INTO disttable VALUES ('2017-09-01 06:01', 5, 40.0) RETURNING *; - --- Generated columns with SELECT -SELECT * FROM disttable ORDER BY 1; - --- Check distributed hypertable within procedure properly drops remote tables --- --- #3663 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -CREATE PROCEDURE test_drop() LANGUAGE PLPGSQL AS $$ -BEGIN - DROP TABLE test; -END -$$; -CALL test_drop(); -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -DROP TABLE test; - - --- Test that stable functions are calculated on the access node. --- --- As a stable function to test, use the timestamp -> timestamptz conversion --- that is stable because it uses the current timezone. --- We have to be careful about `timestamp < timestamptz` comparison. From postgres --- docs: --- When comparing a timestamp without time zone to a timestamp with time zone, --- the former value is assumed to be given in the time zone specified by the --- TimeZone configuration parameter, and is rotated to UTC for comparison to --- the latter value (which is already in UTC internally). --- We don't want this to happen on data node, so we cast the filter value to --- timestamp, and check that this cast happens on the access node and uses the --- current timezone. - -SELECT test.tsl_override_current_timestamptz(null); -CREATE TABLE test_tz (time timestamp, v int); -SELECT create_distributed_hypertable('test_tz','time', - chunk_time_interval => interval '1 hour'); -INSERT INTO test_tz VALUES ('2018-01-02 12:00:00', 2), ('2018-01-02 11:00:00', 1), - ('2018-01-02 13:00:00', 3), ('2018-01-02 14:00:00', 4); - -SET TIME ZONE 'Etc/GMT'; - -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - --- Normal WHERE clause on baserel -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - --- Also test different code paths used with aggregation pushdown. -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - --- TODO: test HAVING here and in the later now() tests as well. - --- Change the timezone and check that the conversion is applied correctly. -SET TIME ZONE 'Etc/GMT+1'; -SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -EXPLAIN (verbose, costs off) -SELECT * FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - -EXPLAIN (verbose, costs off) -SELECT count(*) FROM test_tz WHERE time > '2018-01-02 12:00:00 +00'::timestamptz::timestamp; - --- Conversion to timestamptz cannot be evaluated at the access node, because the --- argument is a column reference. -SELECT count(*) FROM test_tz WHERE time::timestamptz > now(); - --- According to our docs, JIT is not recommended for use on access node in --- multi-node environment. Turn it off so that it doesn't ruin EXPLAIN for the --- next query. -SET jit = 0; - --- Test that operators are evaluated as well. Comparison of timestamp with --- timestamptz is a stable operator, and comparison of two timestamps is an --- immutable operator. This also test that immutable functions using these --- operators as arguments are evaluated. -EXPLAIN (verbose, costs off) -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT * FROM test_tz, dummy -WHERE time > x - + (x = x)::int -- stable - * (x = '2018-01-02 11:00:00'::timestamp)::int -- immutable - * INTERVAL '1 hour'; - --- Reference value for the above test. -WITH dummy AS (SELECT '2018-01-02 12:00:00 +00'::timestamptz::timestamp x) -SELECT x + (x = x)::int * (x = '2018-01-02 11:00:00'::timestamp)::int * INTERVAL '1 hour' -FROM dummy; - --- Exercise some more stable timestamp-related functions. -EXPLAIN (COSTS OFF, VERBOSE) -SELECT * FROM test_tz WHERE date_trunc('month', time) > date_in('2021-01-01') - AND time::time > '00:00:00'::time - + (INTERVAL '1 hour') * date_part('hour', INTERVAL '1 hour'); - - --- Check that the test function for partly overriding now() works. It's very --- hacky and only has effect when we estimate some costs or evaluate sTABLE --- functions in quals on access node, and has no effect in other cases. --- Consider deleting it altogether. -SELECT test.tsl_override_current_timestamptz('2018-01-02 12:00:00 +00'::timestamptz); -SELECT count(*) FROM test_tz WHERE time > now(); -SELECT test.tsl_override_current_timestamptz(null); - -RESET TIME ZONE; -DROP TABLE test_tz; - --- Check that now() is evaluated on the access node. Also check that it is evaluated --- anew on every execution of a prepared statement. -CREATE TABLE test_now (time timestamp, v int); - -SELECT create_distributed_hypertable('test_now','time', - chunk_time_interval => interval '1 hour'); - -PREPARE test_query as -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; -; - -BEGIN; -- to fix the value of now(); - -INSERT INTO test_now VALUES - (now(), 1), (now() + INTERVAL '1 hour', 1), - (now() + INTERVAL '2 hour', 2 ), (now() + INTERVAL '3 hour', 3); - -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - -EXECUTE test_query; - --- Also test different code paths used with aggregation pushdown. --- We can't run EXPLAIN here, because now() is different every time. But the --- strict equality should be enough to detect if now() is being erroneously --- evaluated on data node, where it will differ from time to time. -SELECT count(*) FROM test_now WHERE time = now(); - -COMMIT; - --- now() will be different in a new transaction. -BEGIN; - -SELECT count(*) FILTER (WHERE time = now()), count(*) FILTER (WHERE time < now()), - count(*) FILTER (WHERE time > now()) FROM test_now; - -EXECUTE test_query; - -SELECT count(*) FROM test_now WHERE time = now(); - -COMMIT; - -DROP TABLE test_now; - -DEALLOCATE test_query; - --- Check enabling distributed compression within a --- procedure/function works --- --- #3705 --- -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -CREATE PROCEDURE test_set_compression() LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); -END -$$; -CALL test_set_compression(); -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); -DROP TABLE test; - -CREATE TABLE test (time timestamp, v int); -SELECT create_distributed_hypertable('test','time'); -CREATE FUNCTION test_set_compression_func() RETURNS BOOL LANGUAGE PLPGSQL AS $$ -BEGIN - ALTER TABLE test SET (timescaledb.compress); - RETURN TRUE; -END -$$; -SELECT test_set_compression_func(); -INSERT INTO test VALUES (now(), 0); -SELECT compress_chunk(show_chunks) FROM show_chunks('test'); -DROP TABLE test; - --- Fix ALTER SET/DROP NULL constraint on distributed hypertable --- --- #3860 --- -CREATE TABLE test (time timestamp NOT NULL, my_column int NOT NULL); -SELECT create_distributed_hypertable('test','time'); - -\set ON_ERROR_STOP 0 -INSERT INTO test VALUES (now(), NULL); -\set ON_ERROR_STOP 1 - -ALTER TABLE test ALTER COLUMN my_column DROP NOT NULL; -INSERT INTO test VALUES (now(), NULL); - -\set ON_ERROR_STOP 0 -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; -\set ON_ERROR_STOP 1 - -DELETE FROM test; -ALTER TABLE test ALTER COLUMN my_column SET NOT NULL; - -DROP TABLE test; - --- Test insert into distributed hypertable with pruned chunks - -CREATE TABLE pruned_chunks_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_1', 'time', 'sensor_id'); - -INSERT INTO pruned_chunks_1 VALUES ('2020-12-09',1,32.2); - -CREATE TABLE pruned_chunks_2(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); - --- Convert the table to a distributed hypertable -SELECT table_name FROM create_distributed_hypertable('pruned_chunks_2', 'time', 'sensor_id'); - -insert into pruned_chunks_2 select * from pruned_chunks_1; -insert into pruned_chunks_2 select * from pruned_chunks_1 WHERE time > '2022-01-01'; - --- TEST freeze_chunk api. does not work for distributed chunks -SELECT chunk_schema || '.' || chunk_name as "CHNAME" -FROM timescaledb_information.chunks -WHERE hypertable_name = 'pruned_chunks_1' -ORDER BY chunk_name LIMIT 1 -\gset - -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( :'CHNAME'); -\set ON_ERROR_STOP 1 - ---TEST freeze_chunk api for regular hypertables. Works only for >= PG14 -CREATE TABLE freeze_1(time TIMESTAMPTZ NOT NULL, sensor_id INTEGER, value FLOAT); -SELECT table_name FROM create_hypertable('freeze_1', 'time'); -INSERT INTO freeze_1 VALUES ('2020-12-09',1,32.2); -\set ON_ERROR_STOP 0 -SELECT _timescaledb_functions.freeze_chunk( ch) FROM ( select show_chunks('freeze_1') ch ) q; -\set ON_ERROR_STOP 1 - -DROP TABLE pruned_chunks_1; -DROP TABLE pruned_chunks_2; - --- Cleanup -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_move_chunk.sql.in b/tsl/test/sql/dist_move_chunk.sql.in deleted file mode 100644 index a552f439140..00000000000 --- a/tsl/test/sql/dist_move_chunk.sql.in +++ /dev/null @@ -1,261 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - -SELECT sum(device) FROM dist_test; -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); - --- ensure data node name is provided and has proper type -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> null, destination_node => :'DATA_NODE_2'); -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => null); -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => 2); -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node => :'DATA_NODE_1'); -\set ON_ERROR_STOP 1 - --- ensure functions can't be run in read only mode -SET default_transaction_read_only TO on; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 -SET default_transaction_read_only TO off; - --- ensure functions can't be run in an active multi-statement transaction -\set ON_ERROR_STOP 0 -BEGIN; -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ROLLBACK; -BEGIN; -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -ROLLBACK; -\set ON_ERROR_STOP 1 - --- must be superuser to copy/move chunks -SET ROLE :ROLE_DEFAULT_PERM_USER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 -SET ROLE :ROLE_1; - --- can't run copy/move chunk on a data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- ensure that hypertable chunks are distributed -CREATE TABLE nondist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_hypertable('nondist_test', 'time', 'device', 3); -INSERT INTO nondist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -SELECT * from show_chunks('nondist_test'); -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._hyper_2_5_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 - --- ensure that chunk exists on a source data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_2_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 - --- do actualy copy -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_2'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); - --- ensure that chunk exists on a destination data node -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -\set ON_ERROR_STOP 1 - --- now try to move the same chunk from data node 2 to 3 -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk; $$); -SELECT sum(device) FROM dist_test; - --- Check that they can be called from inside a procedure without --- generating warnings or error messages (#3495). -CREATE OR REPLACE PROCEDURE copy_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.copy_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; - -CREATE OR REPLACE PROCEDURE move_wrapper(regclass, text, text) -AS $$ -BEGIN - CALL timescaledb_experimental.move_chunk($1, $2, $3); -END -$$ -LANGUAGE PLPGSQL; - -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - -CALL copy_wrapper('_timescaledb_internal._dist_hyper_1_3_chunk', :'DATA_NODE_3', :'DATA_NODE_2'); -CALL move_wrapper('_timescaledb_internal._dist_hyper_1_2_chunk', :'DATA_NODE_2', :'DATA_NODE_1'); - -SELECT chunk_name, replica_nodes, non_replica_nodes -FROM timescaledb_experimental.chunk_replication_status; - -DROP PROCEDURE copy_wrapper; -DROP PROCEDURE move_wrapper; - -DROP TABLE dist_test; - --- Test copy/move compressed chunk --- - --- Create a compressed hypertable -CREATE TABLE dist_test(time timestamp NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('dist_test', 'time', 'device', 3); -INSERT INTO dist_test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; -ALTER TABLE dist_test SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); - --- Integrity check (see below) -SELECT sum(device) FROM dist_test; - --- Get a list of chunks -SELECT * from show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - --- Compress a chunk -SELECT compress_chunk('_timescaledb_internal._dist_hyper_3_12_chunk'); -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - --- Get compressed chunk name on the source data node and show its content -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; - -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - --- Get compressed chunk stat -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - --- Move compressed chunk from data node 1 to data node 2 -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_1', destination_node => :'DATA_NODE_2'); -SELECT count(*) FROM _timescaledb_catalog.chunk_copy_operation; - --- Make sure same compressed chunk hash been created on the destination data node -\c :DATA_NODE_2 :ROLE_CLUSTER_SUPERUSER; - --- Chunk created on data node has different id but the same name, make sure --- compressed_chunk_id is correctly set -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - --- Try to query hypertable member with compressed chunk -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; - --- Ensure that compressed chunk stats match stats from the source data node -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - --- Ensure moved chunks are no longer present on the source data node -\c :DATA_NODE_1 :ROLE_CLUSTER_SUPERUSER; - -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - -\set ON_ERROR_STOP 0 -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; -\set ON_ERROR_STOP 1 - --- Make sure chunk has been properly moved from AN -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -SELECT * FROM show_chunks('dist_test'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT * from show_chunks('dist_test'); $$); - -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - --- Query distributed hypertable again to query newly moved chunk, make --- sure result has not changed -SELECT sum(device) FROM dist_test; - --- Test operation_id name validation - -\set ON_ERROR_STOP 0 -CALL timescaledb_experimental.move_chunk(operation_id => ' move chunk id ', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -CALL timescaledb_experimental.move_chunk(operation_id => 'ChUnK_MoVe_Op', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -CALL timescaledb_experimental.move_chunk(operation_id => '_ID123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); -\set ON_ERROR_STOP 1 - --- Now copy chunk from data node 2 to data node 3 -CALL timescaledb_experimental.move_chunk(operation_id => 'id123', chunk=>'_timescaledb_internal._dist_hyper_3_12_chunk', source_node=> :'DATA_NODE_2', destination_node => :'DATA_NODE_3'); - -\c :DATA_NODE_3 :ROLE_CLUSTER_SUPERUSER; - --- Validate chunk on data node 3 -SELECT c2.table_name -FROM _timescaledb_catalog.chunk c1 -JOIN _timescaledb_catalog.chunk c2 ON (c1.compressed_chunk_id = c2.id) -WHERE c1.table_name = '_dist_hyper_3_12_chunk'; - -SELECT * FROM _timescaledb_internal.compress_hyper_3_6_chunk ORDER BY device, _ts_meta_min_1; -SELECT * FROM _timescaledb_internal._dist_hyper_3_12_chunk ORDER BY time; -SELECT * FROM _timescaledb_internal.compressed_chunk_stats WHERE chunk_name = '_dist_hyper_3_12_chunk'; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - --- _dist_hyper_3_12_chunk should be moved in data node 3 now -SELECT chunk_schema || '.' || chunk_name, data_nodes -FROM timescaledb_information.chunks -WHERE hypertable_name = 'dist_test'; - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_param.sql b/tsl/test/sql/dist_param.sql deleted file mode 100644 index efb378bf665..00000000000 --- a/tsl/test/sql/dist_param.sql +++ /dev/null @@ -1,406 +0,0 @@ --- 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. - --- Test parameterized data node scan. -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DN_DBNAME_1 :TEST_DBNAME _1 --- pg_regress doesn't drop these databases for repeated invocation such as in --- the flaky check. -set client_min_messages to ERROR; -drop database if exists :"DN_DBNAME_1" with (force); -select 1 from add_data_node('data_node_1', host => 'localhost', - database => :'DN_DBNAME_1'); -grant usage on foreign server data_node_1 to public; -grant create on schema public to :ROLE_1; -set role :ROLE_1; -reset client_min_messages; -\set ON_ERROR_STOP 0 - --- helper function: float -> pseudorandom float [0..1]. -create or replace function mix(x float4) returns float4 as $$ select ((hashfloat4(x) / (pow(2., 31) - 1) + 1) / 2)::float4 $$ language sql; - --- distributed hypertable -create table metric_dist(ts timestamptz, id int, value float); -select create_distributed_hypertable('metric_dist', 'ts', 'id'); -insert into metric_dist - select '2022-02-02 02:02:02+03'::timestamptz + interval '1 year' * mix(x), - mix(x + 1.) * 20, - mix(x + 2.) * 50 - from generate_series(1, 1000000) x(x) -; -analyze metric_dist; -select count(*) from show_chunks('metric_dist'); - --- dictionary -create table metric_name(id int, name text collate "C", - constraint metric_name_name unique (name), - constraint metric_name_id primary key (id)); -insert into metric_name values (1, 'cpu1'), (3, 'cpu3'), (7, 'cpu7'); -insert into metric_name select x, 'other' || x - from generate_series(1000, 10000) x -; -analyze metric_name; - --- for predictable plans -set enable_hashagg to off; -set enable_material to off; -set enable_mergejoin to off; --- not present on PG 12 -\set ECHO errors -select 'set enable_memoize to off' from pg_settings where name = 'enable_memoize' \gexec -\set ECHO all - --- Subquery + IN -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - -explain (costs off, verbose) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - - --- Check that the GUC to disable these plans works. Our cost model is very --- heuristic and may be often wrong, so there needs to be a way to disable them. -set timescaledb.enable_parameterized_data_node_scan to false; - -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - -explain (costs off, verbose) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - -reset timescaledb.enable_parameterized_data_node_scan; - - --- All fetcher types with join -set timescaledb.remote_data_fetcher = 'copy'; - -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - -set timescaledb.remote_data_fetcher = 'cursor'; - -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - -set timescaledb.remote_data_fetcher = 'prepared'; - -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - --- All fetcher types with initplan -set timescaledb.remote_data_fetcher = 'copy'; - -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - - -set timescaledb.remote_data_fetcher = 'cursor'; - -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - - -set timescaledb.remote_data_fetcher = 'prepared'; - -select id, max(value), count(*) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - - --- Should prefer prepared statement data fetcher for these queries. -set timescaledb.remote_data_fetcher = 'auto'; - -explain (analyze, verbose, costs off, timing off, summary off) -select id, max(value), count(*) -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - --- Should reset the prepared cache mode after using the prepared statement fetcher. -call distributed_exec('create or replace procedure assert_auto_plan_cache_mode() as $$ begin assert (select setting from pg_settings where name = ''plan_cache_mode'') = ''auto''; end; $$ language plpgsql;'); -call distributed_exec('call assert_auto_plan_cache_mode();'); - --- Shippable EC join -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - --- Shipping still might make sense if the local table is outer. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist right join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - --- Shipping doesn't make sense if the distributed table is outer. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist -left join (select * from metric_name where name like 'cpu%') t using (id) -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - --- Non-shippable EC join -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name on name = concat('cpu', metric_dist.id) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - - --- Shippable non-EC join. The weird condition is to only use immutable functions --- that can be shipped to the remote node. `id::text` does CoerceViaIO which is --- not generally shippable. And `int4out` returns cstring, not text, that's why --- the `textin` is needed. -select name, max(value), count(*) -from metric_dist join metric_name - on texteq('cpu' || textin(int4out(metric_dist.id)), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name - on texteq('cpu' || textin(int4out(metric_dist.id)), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - - --- Non-shippable non-EC join. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name - on texteq(concat('cpu', textin(int4out(metric_dist.id))), name) -where metric_name.name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - - --- distinct on, order by, limit 1, with subquery -select distinct on (id) - id, ts, value -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, ts, value -limit 1 -; - -explain (costs off, verbose) -select distinct on (id) - id, ts, value -from metric_dist -where id in (select id from metric_name where name like 'cpu%') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, ts, value -limit 1 -; - - --- distinct on, order by, limit 1, with explicit join -select distinct on (name) - name, ts, value -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by name, ts, value -limit 1 -; - -explain (costs off, verbose) -select distinct on (name) - name, ts, value -from metric_dist join metric_name using (id) -where name like 'cpu%' - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by name, ts, value -limit 1 -; - - --- If there are a lot of rows chosen from the local table, the parameterized --- nested loop might download the entire dist table or even more than that (in --- case of not equi-join or duplicate join keys). --- Check that the parameterized plan is not chosen in this case. -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist -join metric_name using (id) -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by name -order by name -; - - --- An interesting special case is when the remote SQL has a parameter, but it is --- the result of an initplan. It's not "parameterized" in the join sense, because --- there is only one param value. This is the most efficient plan for querying a --- small number of ids. -explain (costs off, verbose) -select id, max(value) -from metric_dist -where id = any((select array_agg(id) from metric_name where name like 'cpu%')::int[]) - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -order by id -; - - --- Multiple joins. Test both EC and non-EC (texteq) join in one query. -create table metric_location(id int, location text); -insert into metric_location values (1, 'Yerevan'), (3, 'Dilijan'), (7, 'Stepanakert'); -analyze metric_location; - -select id, max(value) -from metric_dist natural join metric_location natural join metric_name -where name like 'cpu%' and texteq(location, 'Yerevan') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -; - -explain (costs off, verbose) -select id, max(value) -from metric_dist natural join metric_location natural join metric_name -where name like 'cpu%' and texteq(location, 'Yerevan') - and ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -group by id -; - - --- Multiple joins on different variables. Use a table instead of a CTE for saner --- stats. -create table max_value_times as -select distinct on (id) id, ts from metric_dist -where ts between '2022-02-02 02:02:02+03' and '2022-03-03 02:02:02+03' -order by id, value desc -; -analyze max_value_times; - -explain (costs off, verbose) -select id, value -from metric_dist natural join max_value_times natural join metric_name -where name like 'cpu%' -order by 1 -; - --- Two distributed hypertables, each joined to reference and all joined together. --- The query finds the percentage of time points where one metric is higher than --- another, and also tweaked not to use initplans.Requires hash join. -explain (analyze, verbose, costs off, timing off, summary off) -select count(*) filter (where m1.value > m2.value) / count(*) -from metric_dist m1 -join metric_dist m2 using (ts) -where m1.id in (select id from metric_name where name = 'cpu1') - and m2.id in (select id from metric_name where name = 'cpu3') -; - - --- Should prefer reference table join pushdown to all other kinds of plans, --- basically always. Note that we don't actually replicate the ref table here, --- so EXPLAIN ANALYZE would fail. -set role :ROLE_CLUSTER_SUPERUSER; - -alter foreign data wrapper timescaledb_fdw options (add reference_tables 'metric_name'); - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' -group by name -order by name -; - -set timescaledb.enable_parameterized_data_node_scan to false; - -explain (costs off, verbose) -select name, max(value), count(*) -from metric_dist join metric_name using (id) -where name like 'cpu%' -group by name -order by name -; diff --git a/tsl/test/sql/dist_partial_agg.sql.in b/tsl/test/sql/dist_partial_agg.sql.in deleted file mode 100644 index cfba9bf7975..00000000000 --- a/tsl/test/sql/dist_partial_agg.sql.in +++ /dev/null @@ -1,116 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\ir include/remote_exec.sql - -SET ROLE :ROLE_1; -\set TEST_TABLE 'conditions' -\ir 'include/aggregate_table_create.sql' - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; - -SELECT * FROM test.remote_exec('{ db_dist_partial_agg_1, db_dist_partial_agg_2, db_dist_partial_agg_3}', -$$ - CREATE TYPE custom_type AS (high int, low int); -$$); -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- make sure parallel query plans are preferred on data nodes -ALTER DATABASE :DATA_NODE_1 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_2 SET parallel_setup_cost TO 1; -ALTER DATABASE :DATA_NODE_3 SET parallel_setup_cost TO 1; - --- make sure partitionwise aggregation is enabled on data nodes -ALTER DATABASE :DATA_NODE_1 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_2 SET enable_partitionwise_aggregate TO true; -ALTER DATABASE :DATA_NODE_3 SET enable_partitionwise_aggregate TO true; - -SET ROLE :ROLE_1; -SELECT table_name FROM create_distributed_hypertable( 'conditions', 'timec', 'location', 3, chunk_time_interval => INTERVAL '1 day'); - --- We need a lot of data and a lot of chunks to make the planner push down all of the aggregates -\ir 'include/aggregate_table_populate.sql' - -SET enable_partitionwise_aggregate = ON; -SET timescaledb.remote_data_fetcher = 'cursor'; - --- Run an explain on the aggregate queries to make sure expected aggregates are being pushed down. --- Grouping by the paritioning column should result in full aggregate pushdown where possible, --- while using a non-partitioning column should result in a partial pushdown -\set PREFIX 'EXPLAIN (VERBOSE, COSTS OFF)' - -\set GROUPING 'location' -\ir 'include/aggregate_queries.sql' - -\set GROUPING 'region, temperature' -\ir 'include/aggregate_queries.sql' - --- Full aggregate pushdown correctness check, compare location grouped query results with partionwise aggregates on and off -\set GROUPING 'location' -SELECT format('%s/results/dist_agg_loc_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST1", - format('%s/results/dist_agg_loc_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL1" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL1', :'RESULTS_TEST1') as "DIFF_CMD1" -\gset - ---generate the results into two different files -\set ECHO errors -SET client_min_messages TO error; ---make output contain query results -\set PREFIX '' -\o :RESULTS_CONTROL1 -SET enable_partitionwise_aggregate = OFF; -\ir 'include/aggregate_queries.sql' -\o -\o :RESULTS_TEST1 -SET enable_partitionwise_aggregate = ON; -\ir 'include/aggregate_queries.sql' -\o -\set ECHO all - -:DIFF_CMD1 - --- Partial aggregate pushdown correctness check, compare region grouped query results with partionwise aggregates on and off -\set GROUPING 'region' -SELECT format('%s/results/dist_agg_region_results_test.out', :'TEST_OUTPUT_DIR') as "RESULTS_TEST2", - format('%s/results/dist_agg_region_results_control.out', :'TEST_OUTPUT_DIR') as "RESULTS_CONTROL2" -\gset -SELECT format('\! diff %s %s', :'RESULTS_CONTROL2', :'RESULTS_TEST2') as "DIFF_CMD2" -\gset - ---generate the results into two different files -\set ECHO errors -SET client_min_messages TO error; ---make output contain query results -\set PREFIX '' -\o :RESULTS_CONTROL2 -SET enable_partitionwise_aggregate = OFF; -\ir 'include/aggregate_queries.sql' -\o -\o :RESULTS_TEST2 -SET enable_partitionwise_aggregate = ON; -CALL distributed_exec($$ SET enable_partitionwise_aggregate = ON $$); -\ir 'include/aggregate_queries.sql' -\o -\set ECHO all - -:DIFF_CMD2 - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_policy.sql b/tsl/test/sql/dist_policy.sql deleted file mode 100644 index dbc90d99b7b..00000000000 --- a/tsl/test/sql/dist_policy.sql +++ /dev/null @@ -1,95 +0,0 @@ --- 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. - --- Need to be super user to create extension and add data nodes -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\unset ECHO -\o /dev/null -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; --- though user on access node has required GRANTS, this will propagate GRANTS to the connected data nodes -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- Create a fake clock that we can use below and make sure that it is --- defined on the data nodes as well. -CREATE TABLE time_table (time BIGINT); -INSERT INTO time_table VALUES (1); -CREATE OR REPLACE FUNCTION dummy_now() -RETURNS BIGINT -LANGUAGE SQL -STABLE AS 'SELECT time FROM time_table'; -GRANT ALL ON TABLE time_table TO PUBLIC; - -SELECT * FROM test.remote_exec(NULL, $$ - CREATE TABLE time_table (time BIGINT); - INSERT INTO time_table VALUES (1); - CREATE OR REPLACE FUNCTION dummy_now() - RETURNS BIGINT - LANGUAGE SQL - STABLE AS 'SELECT time FROM time_table'; - GRANT ALL ON TABLE time_table TO PUBLIC; -$$); - -SET ROLE :ROLE_1; -CREATE TABLE conditions( - time BIGINT NOT NULL, - device INT, - value FLOAT -); - -SELECT * FROM create_distributed_hypertable('conditions', 'time', 'device', 3, - chunk_time_interval => 5); -SELECT set_integer_now_func('conditions', 'dummy_now'); - -INSERT INTO conditions -SELECT time, device, random()*80 -FROM generate_series(1, 40) AS time, - generate_series(1,3) AS device -ORDER BY time, device; - -SELECT add_retention_policy('conditions', 5, true) as retention_job_id \gset - --- Now simulate drop_chunks running automatically by calling it --- explicitly. Show chunks before and after. -SELECT show_chunks('conditions'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('conditions'); $$); -UPDATE time_table SET time = 20; -SELECT * FROM test.remote_exec(NULL, $$ UPDATE time_table SET time = 20; $$); -CALL run_job(:retention_job_id); -SELECT show_chunks('conditions'); -SELECT * FROM test.remote_exec(NULL, $$ SELECT show_chunks('conditions'); $$); - -SELECT remove_retention_policy('conditions'); - --- Check that we can insert into the table without the retention --- policy and not get an error. This will be a problem if the policy --- did not propagate drop_chunks to data nodes. -INSERT INTO conditions -SELECT time, device, random()*80 -FROM generate_series(1,10) AS time, - generate_series(1,3) AS device; - --- Make sure reorder policy is blocked for distributed hypertable -\set ON_ERROR_STOP 0 -SELECT add_reorder_policy('conditions', 'conditions_time_idx'); -\set ON_ERROR_STOP 1 - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - diff --git a/tsl/test/sql/dist_query.sql.in b/tsl/test/sql/dist_query.sql.in deleted file mode 100644 index c283bf841b1..00000000000 --- a/tsl/test/sql/dist_query.sql.in +++ /dev/null @@ -1,189 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set TEST_BASE_NAME dist_query --- Run -SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') AS "TEST_LOAD_NAME", - format('include/%s_run.sql', :'TEST_BASE_NAME') AS "TEST_QUERY_NAME", - format('%s/results/%s_results_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REFERENCE", - format('%s/results/%s_results_repartitioning_reference.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_REFERENCE", - format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_OPTIMIZED", - format('%s/results/%s_results_repartitioning_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_REPART_OPTIMIZED", - format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_UNOPTIMIZED", - format('%s/results/%s_results_1dim.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') AS "TEST_RESULTS_1DIM" -\gset -SELECT format('\! diff %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_UNOPT", - format('\! diff %s %s', :'TEST_RESULTS_OPTIMIZED', :'TEST_RESULTS_REFERENCE') AS "DIFF_CMD_OPT", - format('\! diff %s %s', :'TEST_RESULTS_REPART_OPTIMIZED', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_REPART", - format('\! diff %s %s', :'TEST_RESULTS_1DIM', :'TEST_RESULTS_REPART_REFERENCE') AS "DIFF_CMD_1DIM" -\gset - - --- Use a small fetch size to make sure that result are fetched across --- multiple fetches. ---ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fetch_size '500'); -SET client_min_messages TO notice; - --- Load the data -\ir :TEST_LOAD_NAME -SELECT hypertable_schema, hypertable_name, num_dimensions, num_chunks -FROM timescaledb_information.hypertables -ORDER BY 1,2; -SELECT count(*) FROM hyper; - -SELECT count(*) FROM hyper WHERE :CLEAN_PARTITIONING_TIME_RANGE; - -SET enable_partitionwise_aggregate = ON; -\set ECHO errors -\set PREFIX 'EXPLAIN (verbose, costs off)' -\set TABLE_NAME 'hyper' --- Print queries to stdout and send to server -\set OUTPUT_CMD '\\p \\g' - --- For predictable plans -set enable_hashjoin to off; -set enable_mergejoin to off; -set enable_hashagg to off; - ---------------------------------------------------------------------- --- EXPLAINs without ordering ---------------------------------------------------------------------- -\set ORDER_BY_1 '' -\set ORDER_BY_1_2 '' -\set LIMIT '' -\echo - --- Run the EXPLAINs on the cleanly partitioned time range (push-downs --- safe) -\set WHERE_CLAUSE ':CLEAN_PARTITIONING_TIME_RANGE' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- EXPLAINs with ordering ---------------------------------------------------------------------- -\set ORDER_BY_1 'ORDER BY 1' -\set ORDER_BY_1_2 'ORDER BY 1,2' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- EXPLAINs with ordering and querying only one node ---------------------------------------------------------------------- -\set WHERE_CLAUSE ':CLEAN_PARTITIONING_TIME_RANGE AND device = 1' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- EXPLAINs with LIMIT ---------------------------------------------------------------------- -\set WHERE_CLAUSE ':CLEAN_PARTITIONING_TIME_RANGE' -\set LIMIT 'LIMIT 10' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- Run the EXPLAINs on the repartitioned time range (push-downs --- unsafe) ---------------------------------------------------------------------- -\set ORDER_BY_1 '' -\set LIMIT -\set WHERE_CLAUSE ':REPARTITIONED_TIME_RANGE' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- EXPLAINs on a one-dimensional hypertable ---------------------------------------------------------------------- -\set ORDER_BY_1 'ORDER BY 1' -\set ORDER_BY_1_2 '' -\set TABLE_NAME 'hyper1d' -\set OUTPUT_CMD '\\p \\g' -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- ---------------------------------------------------------------------- --- QUERY results (diff test). Note that we need to run the diff tests --- with ordering or else the output will differ depending on table. ---------------------------------------------------------------------- ---------------------------------------------------------------------- - --- Run the queries for each setting. Each setting's result is --- generated into its own file - --- Set extra_float_digits to avoid rounding differences between PG --- versions -SET extra_float_digits=-2; - -\set ECHO errors --- Only execute queries on server (do not print queries) -\set OUTPUT_CMD '\\g' -SET client_min_messages TO error; - -\set PREFIX -\set TABLE_NAME 'reference' -\set ORDER_BY_1 'ORDER BY 1' -\set ORDER_BY_1_2 'ORDER BY 1,2' -\set LIMIT '' -\o :TEST_RESULTS_REPART_REFERENCE - - ---------------------------------------------------------------------- --- Run queries across time range that involve repartitioning (no push --- down) on a two-dimensional table ---------------------------------------------------------------------- -\set WHERE_CLAUSE ':REPARTITIONED_TIME_RANGE' - -\ir :TEST_QUERY_NAME - -\set TABLE_NAME 'hyper' -\o :TEST_RESULTS_REPART_OPTIMIZED -SET enable_partitionwise_aggregate = ON; -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- Now run queries across time range that does not involve --- repartitioning (should use push down) ---------------------------------------------------------------------- -\set WHERE_CLAUSE ':CLEAN_PARTITIONING_TIME_RANGE' -\set TABLE_NAME 'reference' -\o :TEST_RESULTS_REFERENCE -\ir :TEST_QUERY_NAME - -\set TABLE_NAME 'hyper' -\o :TEST_RESULTS_UNOPTIMIZED -SET enable_partitionwise_aggregate = OFF; -\ir :TEST_QUERY_NAME - -\o :TEST_RESULTS_OPTIMIZED -SET enable_partitionwise_aggregate = ON; -\ir :TEST_QUERY_NAME - ---------------------------------------------------------------------- --- Run queries across a one-dimensional hypertable ---------------------------------------------------------------------- -\set TABLE_NAME 'hyper1d' -\set WHERE_CLAUSE ':REPARTITIONED_TIME_RANGE' -\o :TEST_RESULTS_1DIM -\set ORDER_BY_1 'ORDER BY 1' -\set ORDER_BY_1_2 'ORDER BY 1,2' -\set LIMIT '' -SET enable_partitionwise_aggregate = ON; -CALL distributed_exec($$ SET enable_partitionwise_aggregate = ON $$); -\ir :TEST_QUERY_NAME - ------------------------------------------------------------------------ --- Compute the diff (should be no difference) -\set ECHO all -:DIFF_CMD_UNOPT -:DIFF_CMD_OPT -:DIFF_CMD_REPART -:DIFF_CMD_1DIM - -RESET ROLE; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_ref_table_join.sql.in b/tsl/test/sql/dist_ref_table_join.sql.in deleted file mode 100644 index 5981fec5e18..00000000000 --- a/tsl/test/sql/dist_ref_table_join.sql.in +++ /dev/null @@ -1,478 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; - -\des - -drop table if exists metric; -CREATE table metric(ts timestamptz, id int, value float); -SELECT create_distributed_hypertable('metric', 'ts', 'id'); -INSERT into metric values ('2022-02-02 02:02:02+03', 1, 50); -INSERT into metric values ('2020-01-01 01:01:01+03', 1, 60); -INSERT into metric values ('2000-03-03 03:03:03+03', 1, 70); -INSERT into metric values ('2000-04-04 04:04:03+03', 2, 80); - --- Reference table with generic replication -CREATE table metric_name(id int primary key, name text); -INSERT into metric_name values (1, 'cpu1'); -INSERT into metric_name values (2, 'cpu2'); - -CALL distributed_exec($$CREATE table metric_name(id int primary key, name text);$$); -CALL distributed_exec($$INSERT into metric_name values (1, 'cpu1');$$); -CALL distributed_exec($$INSERT into metric_name values (2, 'cpu2');$$); - --- The reference table as DHT -CREATE TABLE metric_name_dht(id BIGSERIAL, name text); -SELECT create_distributed_hypertable('metric_name_dht', 'id', chunk_time_interval => 9223372036854775807, replication_factor => 3); -INSERT into metric_name_dht (id, name) values (1, 'cpu1'); -INSERT into metric_name_dht (id, name) values (2, 'cpu2'); - --- A local version of the reference table -CREATE table metric_name_local(id int primary key, name text); -INSERT into metric_name_local values (1, 'cpu1'); -INSERT into metric_name_local values (2, 'cpu2'); - -CREATE table reference_table2(id int primary key, name text); -SELECT create_distributed_hypertable('reference_table2', 'id', chunk_time_interval => 2147483647, replication_factor => 3); - -CREATE table local_table(id int primary key, name text); - -SET client_min_messages TO WARNING; - --- Create a table in a different schema -CREATE SCHEMA test1; -GRANT CREATE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -GRANT USAGE ON SCHEMA test1 TO :ROLE_DEFAULT_PERM_USER; -CREATE table test1.table_in_schema(id int primary key, name text); - -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, reference_table2'); - -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_dht'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - -\set ON_ERROR_STOP 0 --- Try to declare a non existing table as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, non_existing_table'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Try to declare a hypertable as reference table -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, reference_table2, metric'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Try to add an empty field -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, , metric'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Try to declare a view as reference table -CREATE VIEW metric_name_view AS SELECT * FROM metric_name; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'metric_name, metric_name_view'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Try to use a table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Try to use a non-existing table in a schema -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables 'test1.table_in_schema_non_existing'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - -\set ON_ERROR_STOP 1 - --- Set empty options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET reference_tables ''); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Remove options -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP reference_tables); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - --- Set options again -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD reference_tables 'metric_name, metric_name_dht, reference_table2'); -SELECT fdwoptions FROM pg_foreign_data_wrapper WHERE fdwname = 'timescaledb_fdw'; - -SET client_min_messages TO DEBUG1; - -\set PREFIX 'EXPLAIN (analyze, verbose, costs off, timing off, summary off)' - --- Analyze tables -ANALYZE metric; -ANALYZE metric_name; -ANALYZE metric_name_dht; - --- Our cost model for these kinds of plans is not so good yet, so make some --- tweaks to always get the join pushdown. -set timescaledb.enable_parameterized_data_node_scan to false; -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '0.08'); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '100.0'); - -------- --- Tests based on results -------- - --- Simple join - -SELECT * FROM metric LEFT JOIN metric_name USING (id); - --- Filter - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; - --- Ordering - -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name ASC; - -SELECT * FROM metric LEFT JOIN metric_name USING (id) order by metric_name.name DESC; - --- Aggregations - -SELECT SUM(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - -SELECT MAX(metric.value), MIN(metric.value) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - -SELECT COUNT(*) FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - --- Aggregations and Renaming - -SELECT SUM(m1.value) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name = 'cpu1'; - -SELECT MAX(m1.value), MIN(m1.value) FROM metric AS m1 LEFT JOIN metric_name AS m2 USING (id) WHERE name = 'cpu1'; - -SELECT COUNT(*) FROM metric AS ma LEFT JOIN metric_name as m2 USING (id) WHERE name = 'cpu1'; - --- Grouping - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name ORDER BY name DESC; - -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name HAVING min(value) > 60 ORDER BY name DESC; - -------- --- Tests based on query plans -------- - --- Tests without filter (vanilla PostgreSQL reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name ON metric.id = metric_name.id; - --- Tests without filter (DHT reftable) -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id); - --- Tests with filter pushdown -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > 10; - -PREPARE prepared_join_pushdown_value (int) AS - SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE value > $1; - -:PREFIX -EXECUTE prepared_join_pushdown_value(10); - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts > '2022-02-02 02:02:02+03'; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu2'; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name_dht USING (id) WHERE name LIKE 'cpu%'; - --- Tests with an expression that evaluates to false -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu1' AND name LIKE 'cpu2'; - --- Tests with aliases -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id); - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id; - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10; - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 ON m1.id = m2.id WHERE m1.value > 10 AND m2.name LIKE 'cpu%'; - --- Tests with projections -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT m1.ts, m1.value FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT m1.id, m1.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT m1.id, m2.id FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT m1.*, m2.* FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03'; - --- Ordering -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS first; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name ASC NULLS last; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS first; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name DESC NULLS last; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY name, value DESC; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name DESC; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC, name DESC; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value ASC NULLS last, name DESC NULLS first; - --- Ordering with explicit table qualification -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id; - -:PREFIX -SELECT name, value FROM metric LEFT JOIN metric_name USING (id) ORDER BY value, name, metric_name.id, metric.id; - --- Ordering with explicit table qualification and aliases -:PREFIX -SELECT name, value FROM metric m1 LEFT JOIN metric_name m2 USING (id) ORDER BY value, name, m1.id, m2.id; - --- Grouping -:PREFIX -SELECT name FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; - -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' GROUP BY name; - -:PREFIX -SELECT name, max(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' AND ts BETWEEN '2022-02-02 02:02:02+03' AND '2022-02-02 02:12:02+03' GROUP BY name; - --- Grouping and sorting -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name ORDER BY name DESC; - --- Having -:PREFIX -SELECT name, max(value), min(value) FROM metric LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' and ts BETWEEN '2000-02-02 02:02:02+03' and '2022-02-02 02:12:02+03' GROUP BY name having min(value) > 0 ORDER BY name DESC; - --- Rank -:PREFIX -SELECT name, value, RANK () OVER (ORDER by value) from metric join metric_name_local USING (id); - --- Check returned types -SELECT pg_typeof("name"), pg_typeof("id"), pg_typeof("value"), name, id, value FROM metric -LEFT JOIN metric_name USING (id) WHERE name LIKE 'cpu%' LIMIT 1; - --- Left join and reference table on the left hypertable on the right (no pushdown) -:PREFIX -SELECT * FROM metric_name LEFT JOIN metric USING (id) WHERE name LIKE 'cpu%'; - --- Right join reference table on the left, hypertable on the right (can be converted into a left join by PostgreSQL, pushdown) -:PREFIX -SELECT * FROM metric_name RIGHT JOIN metric USING (id) WHERE name LIKE 'cpu%'; - --- Right join hypertable on the left, reference table on the right (no pushdown) -:PREFIX -SELECT * FROM metric RIGHT JOIN metric_name USING (id) WHERE name LIKE 'cpu%'; - --- Inner join and reference table left, hypertable on the right (pushdown) -:PREFIX -SELECT * FROM metric_name INNER JOIN metric USING (id) WHERE name LIKE 'cpu%'; - --- Implicit join on two tables, hypertable left, reference table right (pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2 WHERE m1.id=m2.id AND name LIKE 'cpu%'; - --- Implicit join on two tables, reference table left, hypertable right (pushdown) -:PREFIX -SELECT * FROM metric m2, metric_name m1 WHERE m1.id=m2.id AND name LIKE 'cpu%'; - --- Implicit join on three tables (no pushdown) -:PREFIX -SELECT * FROM metric m1, metric_name m2, metric_name m3 WHERE m1.id=m2.id AND m2.id = m3.id AND m3.name LIKE 'cpu%'; - --- Left join on a DHT and a subselect on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name) AS sub ON metric.id=sub.id; - --- Left join on a DHT and a subselect with filter on a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM metric LEFT JOIN (SELECT * FROM metric_name WHERE name LIKE 'cpu%') AS sub ON metric.id=sub.id; - --- Left join on a subselect on a DHT and a reference table (subselect can be removed, pushdown) -:PREFIX -SELECT * FROM (SELECT * FROM metric) as sub LEFT JOIN metric_name ON sub.id=metric_name.id WHERE name LIKE 'cpu%'; - --- Left join and hypertable on left and right (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) WHERE m1.id = 2; - --- Left join and reference table on left and right -:PREFIX -SELECT * FROM metric_name m1 LEFT JOIN metric_name m2 USING (id) WHERE m1.name LIKE 'cpu%'; - --- Only aggregation no values needs to be transferred -:PREFIX -SELECT count(*) FROM metric m1 LEFT JOIN metric_name m2 USING (id) WHERE m2.name LIKE 'cpu%'; - --- Lateral joins that can be converted into regular joins -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id = m2.id) t ON TRUE; - -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id) t ON TRUE; - --- Lateral join that can not be converted and pushed down -:PREFIX -SELECT * FROM metric m1 LEFT JOIN LATERAL (SELECT * FROM metric_name m2 WHERE m1.id > m2.id ORDER BY m2.name LIMIT 1) t ON TRUE; - --- Two left joins (no pushdown) -:PREFIX -SELECT * FROM metric m1 LEFT JOIN metric m2 USING (id) LEFT JOIN metric_name mn USING(id); - -------- --- Tests with shippable and non-shippable joins / EquivalenceClass --- See 'dist_param.sql' for an explanation of the used textin / int4out --- functions. -------- - --- Shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq('cpu' || textin(int4out(metric.id)), name) -GROUP BY name -ORDER BY name; - --- Non-shippable equality class join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON name = concat('cpu', metric.id) -GROUP BY name -ORDER BY name; - --- Non-shippable non-EquivalenceClass join -:PREFIX -SELECT name, max(value), count(*) -FROM metric JOIN metric_name ON texteq(concat('cpu', textin(int4out(metric.id))), name) -GROUP BY name -ORDER BY name; - -------- --- MERGE is supported in PG >= 15. Currently, it is not supported in TimescaleDB --- on distributed hypertables. Perform a MERGE here to check if the join pushdown --- can handle the MERGE command properly. ON_ERROR_STOP is disabled for this test. --- Older PostgreSQL versions report an error because MERGE is not supported. This --- will be ignored due to the setting. --- Commenting below test as error meesage is different on windows vs unix. --- Issue #5725 is opened to track it. -------- --- \set ON_ERROR_STOP 0 --- MERGE INTO metric as target_0 --- USING metric as input_0 --- inner join (select id from metric_name as input_1) as subq_0 --- ON (TRUE) --- ON target_0.id = input_0.id --- WHEN MATCHED --- THEN DO NOTHING --- WHEN NOT MATCHED --- THEN DO NOTHING; --- \set ON_ERROR_STOP 1 - -------- --- Tests without enable_per_data_node_queries (no pushdown supported) -------- -SET timescaledb.enable_per_data_node_queries = false; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - -SET timescaledb.enable_per_data_node_queries = true; - -------- --- Tests with empty reftable -------- -RESET client_min_messages; -TRUNCATE metric_name; -CALL distributed_exec($$TRUNCATE metric_name;$$); - --- Left join -SELECT * FROM metric LEFT JOIN metric_name USING (id); - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id); - --- Inner join -SELECT * FROM metric JOIN metric_name USING (id); - -:PREFIX -SELECT * FROM metric JOIN metric_name USING (id); - --- Filter on the NULL column -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name IS NOT NULL; - -:PREFIX -SELECT * FROM metric LEFT JOIN metric_name USING (id) WHERE name = 'cpu1'; - -------- --- Drop reftable on DNs and check proper error reporting -------- -\set ON_ERROR_STOP 0 -CALL distributed_exec($$DROP table metric_name;$$); - -SELECT * FROM metric LEFT JOIN metric_name USING (id); diff --git a/tsl/test/sql/dist_remote_error.sql.in b/tsl/test/sql/dist_remote_error.sql.in deleted file mode 100644 index 4faa33d816d..00000000000 --- a/tsl/test/sql/dist_remote_error.sql.in +++ /dev/null @@ -1,324 +0,0 @@ --- 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 DATA_NODE_1 data_node_1 ---\set DATA_NODE_2 data_node_2 ---\set DATA_NODE_3 data_node_3 - --- Set up the data nodes. -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -\c :TEST_DBNAME :ROLE_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; - --- Import setup file to data nodes. -\unset ECHO -\c :DATA_NODE_1 :ROLE_SUPERUSER -set client_min_messages to error; -\ir include/dist_remote_error_setup.sql - -\c :DATA_NODE_2 :ROLE_SUPERUSER -set client_min_messages to error; -\ir include/dist_remote_error_setup.sql - -\set sleepy_sendrecv 1 -\c :DATA_NODE_3 :ROLE_SUPERUSER -set client_min_messages to error; -\ir include/dist_remote_error_setup.sql -\unset sleepy_sendrecv - -\c :TEST_DBNAME :ROLE_SUPERUSER -set client_min_messages to error; -\ir include/dist_remote_error_setup.sql -\set ECHO all - --- Disable SSL to get stable error output across versions. SSL adds some output --- that changed in PG 14. -set timescaledb.debug_enable_ssl to off; - -set client_min_messages to error; - -SET timescaledb.hide_data_node_name_in_errors = 'on'; - --- A relatively big table on one data node -CREATE TABLE metrics_dist_remote_error(filler_1 int, filler_2 int, filler_3 int, time timestamptz NOT NULL, device_id int, v0 int, v1 int, v2 float, v3 float); -SELECT create_distributed_hypertable('metrics_dist_remote_error','time','device_id',3, - data_nodes => ARRAY[:'DATA_NODE_1']); - -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_1; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-01 0:00:00+0'::timestamptz,'2000-01-05 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_2; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-06 0:00:00+0'::timestamptz,'2000-01-12 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ALTER TABLE metrics_dist_remote_error DROP COLUMN filler_3; -INSERT INTO metrics_dist_remote_error(time,device_id,v0,v1,v2,v3) SELECT time, device_id, device_id+1, device_id + 2, device_id + 0.5, NULL FROM generate_series('2000-01-13 0:00:00+0'::timestamptz,'2000-01-19 23:55:00+0','6m') gtime(time), generate_series(1,5,1) gdevice(device_id); -ANALYZE metrics_dist_remote_error; - --- The error messages vary wildly between the Postgres versions, dependent on --- the particular behavior of libqp in this or that case. The purpose of this --- test is not to solidify this accidental behavior, but to merely exercise the --- error handling code to make sure it doesn't have fatal errors. Unfortunately, --- there is no way to suppress error output from a psql script. -set client_min_messages to ERROR; - -\set ON_ERROR_STOP off - -set timescaledb.remote_data_fetcher = 'copy'; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(16384, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - --- We don't test fatal errors here, because PG versions before 14 are unable to --- report them properly to the access node, so we get different errors in these --- versions. - --- Now test the same with the cursor fetcher. -set timescaledb.remote_data_fetcher = 'cursor'; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - --- Now test the same with the prepared statement fetcher. -set timescaledb.remote_data_fetcher = 'prepared'; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(0, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(1, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(2, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(701, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000, device_id)::int != 0; - -explain (analyze, verbose, costs off, timing off, summary off) -select 1 from metrics_dist_remote_error where ts_debug_shippable_error_after_n_rows(10000000, device_id)::int != 0; - -reset timescaledb.remote_data_fetcher; - - --- Table with broken send for a data type. - -create table metrics_dist_bs(like metrics_dist_remote_error); - -alter table metrics_dist_bs alter column v0 type bs; - -select table_name from create_distributed_hypertable('metrics_dist_bs', - 'time', 'device_id'); - -set timescaledb.enable_connection_binary_data to off; -insert into metrics_dist_bs - select * from metrics_dist_remote_error; -set timescaledb.enable_connection_binary_data to on; - -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_bs; - -drop table metrics_dist_bs; - --- Table with broken receive for a data type. -create table metrics_dist_br(like metrics_dist_remote_error); - -alter table metrics_dist_br alter column v0 type br; - -select table_name from create_distributed_hypertable('metrics_dist_br', - 'time', 'device_id'); - -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - --- Test that INSERT and COPY fail on data nodes. --- Note that we use the text format for the COPY input, so that the access node --- doesn't call `recv` and fail by itself. It's going to use binary format for --- transfer to data nodes regardless of the input format. -set timescaledb.dist_copy_transfer_format = 'binary'; - --- First, create the reference. -\copy (select * from metrics_dist_remote_error) to 'dist_remote_error.text' with (format text); - --- We have to test various interleavings of COPY and INSERT to check that --- one can recover from connection failure states introduced by another. -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -insert into metrics_dist_br select * from metrics_dist_remote_error; -insert into metrics_dist_br select * from metrics_dist_remote_error; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); - --- Fail at different points -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -reset timescaledb.debug_broken_sendrecv_error_after; - - --- Same with different replication factor -truncate metrics_dist_br; -select set_replication_factor('metrics_dist_br', 2); -select hypertable_name, replication_factor from timescaledb_information.hypertables -where hypertable_name = 'metrics_dist_br'; - -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -insert into metrics_dist_br select * from metrics_dist_remote_error; -insert into metrics_dist_br select * from metrics_dist_remote_error; -set timescaledb.debug_broken_sendrecv_error_after = 1; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 2; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1023; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1024; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); -set timescaledb.debug_broken_sendrecv_error_after = 1025; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); - --- Should succeed with text format for data transfer. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_br from 'dist_remote_error.text' with (format text); - --- Final check. -set timescaledb.enable_connection_binary_data = false; -select count(*) from metrics_dist_br; -set timescaledb.enable_connection_binary_data = true; - -reset timescaledb.debug_broken_sendrecv_error_after; -drop table metrics_dist_br; - --- Table with sleepy receive for a data type, to improve coverage of the waiting --- code on the access node. -create table metrics_dist_sr(like metrics_dist_remote_error); - -alter table metrics_dist_sr alter column v0 type sr; - -select table_name from create_distributed_hypertable('metrics_dist_sr', - 'time', 'device_id'); - --- We're using sleepy recv function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.dist_copy_transfer_format = 'binary'; - --- Test INSERT and COPY with slow data node. -\copy metrics_dist_sr from 'dist_remote_error.text' with (format text); - -insert into metrics_dist_sr select * from metrics_dist_remote_error; - -select count(*) from metrics_dist_sr; - -drop table metrics_dist_sr; - --- Table with sleepy send for a data type, on one data node, to improve coverage --- of waiting in data fetchers. -create table metrics_dist_ss(like metrics_dist_remote_error); - -alter table metrics_dist_ss alter column v0 type ss; - -select table_name from create_distributed_hypertable('metrics_dist_ss', - 'time', 'device_id'); - --- Populate the table, using text COPY to avoid the sleepy stuff. -set timescaledb.dist_copy_transfer_format = 'text'; -\copy metrics_dist_ss from 'dist_remote_error.text' with (format text); - --- We're using sleepy send function, so need the binary transfer format for it --- to be called on the data nodes. -set timescaledb.enable_connection_binary_data = true; - -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_ss; - --- Incorrect int output, to cover the error handling in tuplefactory. -create table metrics_dist_io(like metrics_dist_remote_error); - -alter table metrics_dist_io alter column v0 type io; - -select table_name from create_distributed_hypertable('metrics_dist_io', - 'time', 'device_id'); - --- Populate the table, using binary COPY to avoid the broken in4out. -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'binary'; -\copy metrics_dist_io from 'dist_remote_error.text' with (format text); - --- For testing, force the text format to exerices our broken out function. -set timescaledb.enable_connection_binary_data = false; -set timescaledb.dist_copy_transfer_format = 'text'; - -set timescaledb.remote_data_fetcher = 'prepared'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; - -set timescaledb.remote_data_fetcher = 'copy'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; - -set timescaledb.remote_data_fetcher = 'cursor'; -explain (analyze, verbose, costs off, timing off, summary off) -select * from metrics_dist_io; - --- cleanup -\c :TEST_DBNAME :ROLE_SUPERUSER; -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/dist_triggers.sql b/tsl/test/sql/dist_triggers.sql deleted file mode 100644 index 5f5965416ff..00000000000 --- a/tsl/test/sql/dist_triggers.sql +++ /dev/null @@ -1,421 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\unset ECHO -\o /dev/null -\ir include/filter_exec.sql -\ir include/remote_exec.sql -\o -\set ECHO all - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 -\set TABLESPACE_1 :TEST_DBNAME _1 -\set TABLESPACE_2 :TEST_DBNAME _2 -SELECT - test.make_tablespace_path(:'TEST_TABLESPACE1_PREFIX', :'TEST_DBNAME') AS spc1path, - test.make_tablespace_path(:'TEST_TABLESPACE2_PREFIX', :'TEST_DBNAME') AS spc2path -\gset - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; - -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; --- Import testsupport.sql file to data nodes -\unset ECHO -\o /dev/null -\c :DATA_NODE_1 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_2 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :DATA_NODE_3 -SET client_min_messages TO ERROR; -\ir :TEST_SUPPORT_FILE -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; -\o -SET client_min_messages TO NOTICE; -\set ECHO all - -SET ROLE :ROLE_1; - -CREATE TABLE hyper ( - time BIGINT NOT NULL, - device_id TEXT NOT NULL, - sensor_1 NUMERIC NULL DEFAULT 1 -); - --- Table to log trigger events -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); - -CREATE OR REPLACE FUNCTION test_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - INSERT INTO public.trigger_events VALUES (TG_WHEN, TG_LEVEL, TG_OP, TG_NAME); - RETURN NEW; -END -$BODY$; - -CALL distributed_exec($$ -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); -$$, ARRAY[:'DATA_NODE_1']); - --- row triggers: BEFORE -CREATE TRIGGER _0_test_trigger_insert - BEFORE INSERT ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_update - BEFORE UPDATE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_delete - BEFORE DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER z_test_trigger_all - BEFORE INSERT OR UPDATE OR DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - --- row triggers: AFTER -CREATE TRIGGER _0_test_trigger_insert_after - AFTER INSERT ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_insert_after_when_dev1 - AFTER INSERT ON hyper - FOR EACH ROW - WHEN (NEW.device_id = 'dev1') - EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_update_after - AFTER UPDATE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_delete_after - AFTER DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER z_test_trigger_all_after - AFTER INSERT OR UPDATE OR DELETE ON hyper - FOR EACH ROW EXECUTE FUNCTION test_trigger(); - - ---- Create some triggers before we turn the table into a distributed ---- hypertable and some triggers after so that we test both cases. -SELECT * FROM create_distributed_hypertable('hyper', 'time', 'device_id', 3, chunk_time_interval => 10, data_nodes => ARRAY[:'DATA_NODE_1', :'DATA_NODE_2']); - -SELECT * FROM _timescaledb_catalog.dimension_partition -ORDER BY 1,2; - --- FAILURE cases -\set ON_ERROR_STOP 0 - --- Check that CREATE TRIGGER fails if a trigger already exists on a data node. -CALL distributed_exec($$ -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); -$$, ARRAY[:'DATA_NODE_1']); - -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - -CALL distributed_exec($$ -DROP TRIGGER _0_test_trigger_insert_s_before ON hyper; -$$, ARRAY[:'DATA_NODE_1']); - --- Test that trigger execution fails if trigger_events table doesn't --- exist on all nodes. Insert should fail -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); -\set ON_ERROR_STOP 1 - --- Now, create trigger_events on the other nodes -CALL distributed_exec($$ -CREATE TABLE trigger_events ( - tg_when text, - tg_level text, - tg_op text, - tg_name text -); -$$, ARRAY[:'DATA_NODE_2', :'DATA_NODE_3']); - --- Test that trigger fails if the user isn't the owner of the trigger --- function on one of the nodes. -RESET ROLE; -CALL distributed_exec($$ - ALTER FUNCTION test_trigger OWNER TO current_user; -$$, ARRAY[:'DATA_NODE_1']); -SET ROLE :ROLE_1; - -\set ON_ERROR_STOP 0 --- Insert should fail since the trigger function on DN1 isn't owned by --- the user. -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); -\set ON_ERROR_STOP 1 - --- Reset the owner of the trigger function on DN1 to the non-superuser -RESET ROLE; -CALL distributed_exec('ALTER FUNCTION test_trigger OWNER TO ' || :'ROLE_1', ARRAY[:'DATA_NODE_1']); -SET ROLE :ROLE_1; - --- Add more triggers after the distributed hypertable is created - --- statement triggers: BEFORE -CREATE TRIGGER _0_test_trigger_insert_s_before - BEFORE INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_update_s_before - BEFORE UPDATE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_delete_s_before - BEFORE DELETE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - --- statement triggers: AFTER -CREATE TRIGGER _0_test_trigger_insert_s_after - AFTER INSERT ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_update_s_after - AFTER UPDATE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - -CREATE TRIGGER _0_test_trigger_delete_s_after - AFTER DELETE ON hyper - FOR EACH STATEMENT EXECUTE FUNCTION test_trigger(); - ---test triggers before create_distributed_hypertable -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987600000000000, 'dev1', 1); - --- Show trigger count on access node. Only statement-level triggers --- fire on the access node. -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; - --- Show trigger counts on data nodes. Both statement-level and --- row-level triggers fire on the data nodes. -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); - -TRUNCATE trigger_events; -CALL distributed_exec($$ -TRUNCATE trigger_events; -$$); - -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987700000000000, 'dev2', 1), (1257987800000000000, 'dev2', 1); - -UPDATE hyper SET sensor_1 = 2; - -DELETE FROM hyper; - -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); - --- Attach a new data node and show that the hypertable is created on --- the node, including its triggers. -SELECT attach_data_node(:'DATA_NODE_3', 'hyper'); -SELECT * FROM _timescaledb_catalog.dimension_partition -ORDER BY 1,2; - --- Show that triggers are created on the new data node after attaching -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], -$$ - SELECT test.show_triggers('hyper'); -$$); - --- Insert data on the new data node to create a chunk and fire --- triggers. -INSERT INTO hyper(time, device_id,sensor_1) VALUES -(1257987700000000000, 'dev4', 1); - -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ -SELECT tg_when, tg_level, tg_op, tg_name, count(*) -FROM trigger_events -GROUP BY 1,2,3,4 -ORDER BY 1,2,3,4; -$$); - ---test drop trigger -DROP TRIGGER _0_test_trigger_insert ON hyper; -DROP TRIGGER _0_test_trigger_insert_s_before ON hyper; -DROP TRIGGER _0_test_trigger_insert_after ON hyper; -DROP TRIGGER _0_test_trigger_insert_s_after ON hyper; - -DROP TRIGGER _0_test_trigger_update ON hyper; -DROP TRIGGER _0_test_trigger_update_s_before ON hyper; -DROP TRIGGER _0_test_trigger_update_after ON hyper; -DROP TRIGGER _0_test_trigger_update_s_after ON hyper; - -DROP TRIGGER _0_test_trigger_delete ON hyper; -DROP TRIGGER _0_test_trigger_delete_s_before ON hyper; -DROP TRIGGER _0_test_trigger_delete_after ON hyper; -DROP TRIGGER _0_test_trigger_delete_s_after ON hyper; - -DROP TRIGGER z_test_trigger_all ON hyper; -DROP TRIGGER z_test_trigger_all_after ON hyper; -DROP TRIGGER _0_test_trigger_insert_after_when_dev1 ON hyper; - --- Triggers are dropped on all data nodes: -SELECT * FROM test.remote_exec(ARRAY[:'DATA_NODE_1', :'DATA_NODE_2', :'DATA_NODE_3'], $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('hyper') st; -$$); - --- Test triggers that modify tuples and make sure RETURNING is done --- properly (i.e., the modified tuple is returned). - --- Add serial (autoincrement) and DEFAULT value columns to test that --- these work with custom insert nodes. -CREATE TABLE disttable( - id serial, - time timestamptz NOT NULL, - device int DEFAULT 100, - temp_c float -); -SELECT * FROM create_distributed_hypertable('disttable', 'time', 'device'); - --- Create a datatable to source data from. Add array of composite data --- type to test switching to text mode below. Arrays include the type --- Oid when serialized in binary format. Since the Oid of a --- user-created type can differ across data nodes, such serialization --- is not safe. -CREATE TABLE datatable (LIKE disttable); -INSERT INTO datatable (id, time, device, temp_c) VALUES - (1, '2017-01-01 06:01', 1, 1), - (2, '2017-01-01 09:11', 3, 2), - (3, '2017-01-01 08:01', 1, 3), - (4, '2017-01-02 08:01', 2, 4), - (5, '2018-07-02 08:01', 87, 5), - (6, '2018-07-01 06:01', 13, 6), - (7, '2018-07-01 09:11', 90, 7), - (8, '2018-07-01 08:01', 29, 8); - -CREATE OR REPLACE FUNCTION temp_increment_trigger() - RETURNS TRIGGER LANGUAGE PLPGSQL AS -$BODY$ -BEGIN - IF TG_OP = 'INSERT' THEN - NEW.temp_c = NEW.temp_c+1.0; - END IF; - RETURN NEW; -END -$BODY$; - --- Add a BEFORE INSERT trigger to see that plan reverts to --- DataNodeDispatch when using RETURNING -CREATE TRIGGER _0_temp_increment - BEFORE INSERT ON disttable - FOR EACH ROW EXECUTE FUNCTION temp_increment_trigger(); - --- Show that the trigger exists on a data node -SELECT test.remote_exec(ARRAY[:'DATA_NODE_3'], $$ SELECT test.show_triggers('disttable') $$); -TRUNCATE disttable; - --- Show EXPLAINs for INSERT first with DataNodeCopy disabled. Should --- always use DataNodeDispatch -SET timescaledb.enable_distributed_insert_with_copy=false; --- Without RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable; - --- With RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable RETURNING *; - --- With DataNodeCopy enabled, should use DataNodeCopy when there's no --- RETURNING clause, but with RETURNING it should use DataNodeDispatch --- due to the modifying trigger. -SET timescaledb.enable_distributed_insert_with_copy=true; --- Without RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable; - --- With RETURNING -EXPLAIN VERBOSE -INSERT INTO disttable (time, device, temp_c) -SELECT time, device, temp_c FROM datatable RETURNING *; - --- Do the actual INSERT, but wrap in CTE to ensure ordered output in --- order to avoid flakiness. The returned rows should have temp_c --- incremented by the trigger -WITH inserted AS ( - INSERT INTO disttable (time, device, temp_c) - SELECT time, device, temp_c FROM datatable RETURNING * -) SELECT * FROM inserted ORDER BY 1; - --- Show that the RETURNING rows are the same as those stored after --- INSERT. Expect temp_c to be incremented by one compared to the --- original data. -SELECT di.id, di.time, di.device, di.temp_c AS temp_c, da.temp_c AS temp_c_orig -FROM disttable di, datatable da -WHERE di.id = da.id -ORDER BY 1; - --- Rename a trigger -ALTER TRIGGER _0_temp_increment ON disttable RENAME TO _1_temp_increment; - --- Show that remote chunks have the new trigger name -SELECT * FROM test.remote_exec(NULL, $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; -$$); - --- Drop the trigger and show that it is dropped on data nodes -DROP TRIGGER _1_temp_increment ON disttable; - -SELECT * FROM test.remote_exec(NULL, $$ -SELECT st."Child" as chunk_relid, test.show_triggers((st)."Child") -FROM test.show_subtables('disttable') st; -$$); - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - diff --git a/tsl/test/sql/dist_util.sql.in b/tsl/test/sql/dist_util.sql.in deleted file mode 100644 index c1eb2c966c8..00000000000 --- a/tsl/test/sql/dist_util.sql.in +++ /dev/null @@ -1,362 +0,0 @@ --- 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. - ----------------------------------------------------------------- --- Test version compability function -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -CREATE OR REPLACE FUNCTION compatible_version(version CSTRING, reference CSTRING) -RETURNS BOOLEAN -AS :TSL_MODULE_PATHNAME, 'ts_test_compatible_version' -LANGUAGE C VOLATILE; - -SELECT * FROM compatible_version('2.0.0-beta3.19', reference => '2.0.0-beta3.19'); -SELECT * FROM compatible_version('2.0.0', reference => '2.0.0'); -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0-beta3.19'); -SELECT * FROM compatible_version('1.9.9', reference => '2.0.0'); -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0-beta3.19'); -SELECT * FROM compatible_version('2.0.9', reference => '2.0.0'); -SELECT * FROM compatible_version('2.1.9', reference => '2.0.0-beta3.19'); -SELECT * FROM compatible_version('2.1.0', reference => '2.1.19-beta3.19'); - --- These should not parse and instead generate an error. -\set ON_ERROR_STOP 0 -SELECT * FROM compatible_version('2.1.*', reference => '2.1.19-beta3.19'); -SELECT * FROM compatible_version('2.1.0', reference => '2.1.*'); -\set ON_ERROR_STOP 1 - ----------------------------------------------------------------- --- Create two distributed databases - -CREATE DATABASE frontend_1; -CREATE DATABASE frontend_2; - -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '87c235e9-d857-4f16-b59f-7fbac9b87664' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_1_1'); -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; -SET client_min_messages TO NOTICE; - --- Create a second frontend database and add a backend to it -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -CREATE EXTENSION timescaledb; -UPDATE _timescaledb_catalog.metadata SET value = '77348176-09da-4a80-bc78-e31bdf5e63ec' WHERE key = 'uuid'; -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_1', host => 'localhost', database => 'backend_2_1'); -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE '%uuid'; -SET client_min_messages TO NOTICE; - -\set ON_ERROR_STOP 0 - ----------------------------------------------------------------- --- Adding frontend as backend to a different frontend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => true); -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_2', bootstrap => false); - ----------------------------------------------------------------- --- Adding backend from a different group as a backend should fail -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); - ----------------------------------------------------------------- --- Adding a valid backend target but to an existing backend should fail -\c backend_1_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => true); -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'backend_2_1', bootstrap => false); - ----------------------------------------------------------------- --- Adding a frontend (frontend 1) as a backend to a nondistributed node (TEST_DBNAME) should fail -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => true); -SELECT * FROM add_data_node('invalid_data_node', host => 'localhost', database => 'frontend_1', bootstrap => false); - -\set ON_ERROR_STOP 1 - ----------------------------------------------------------------- --- Test that a data node can be moved to a different frontend if it is --- removed first. -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => true); - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - --- Now remove a backend from this distributed database to add it to the other cluster -\c frontend_1 :ROLE_CLUSTER_SUPERUSER -SELECT * FROM delete_data_node('data_node_2'); - --- dist_uuid should not be removed from the metadata on the data node, --- so we need to delete it manually before adding it to another --- backend. -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; -DELETE FROM _timescaledb_catalog.metadata WHERE key = 'dist_uuid'; - --- Add the data node to the second frontend without bootstrapping -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -SELECT node_name, database, node_created, database_created, extension_created -FROM add_data_node('data_node_2', host => 'localhost', database => 'backend_x_2', bootstrap => false); - --- dist_uuid should be added to the metadata on the data node -\c backend_x_2 :ROLE_CLUSTER_SUPERUSER -SELECT key, value FROM _timescaledb_catalog.metadata WHERE key LIKE 'dist_uuid'; - --- Test space reporting functions for distributed and non-distributed tables -\c frontend_2 :ROLE_CLUSTER_SUPERUSER -CREATE TABLE nondisttable(time timestamptz, device int CHECK (device > 0), temp float); -CREATE TABLE disttable(time timestamptz, device int CHECK (device > 0), temp float); -SELECT * FROM create_hypertable('nondisttable', 'time', create_default_indexes => false); -SELECT * FROM create_distributed_hypertable('disttable', 'time', create_default_indexes => false); - -SELECT node_name FROM timescaledb_information.data_nodes -ORDER BY node_name; -SELECT * FROM timescaledb_information.hypertables -ORDER BY hypertable_schema, hypertable_name; - --- Test size functions on empty distributed hypertable. --- --- First, show the output from standard PG size functions. The --- functions are expected to remove 0 table bytes for the distributed --- hypertable since it doesn't have local storage. -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('disttable'); -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; - --- Create primary key index and check how it affects the size of the --- empty hypertables. -ALTER TABLE nondisttable ADD CONSTRAINT nondisttable_pkey PRIMARY KEY (time); -ALTER TABLE disttable ADD CONSTRAINT disttable_pkey PRIMARY KEY (time); - -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); -SELECT * FROM _timescaledb_functions.relation_size('disttable'); -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); - --- Note that the empty disttable is three times the size of the --- nondisttable since it has primary key indexes on two data nodes in --- addition to the access node. -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - - --- Test size functions on tables with an empty chunk -INSERT INTO nondisttable VALUES ('2017-01-01 06:01', 1, 1.1); -INSERT INTO disttable SELECT * FROM nondisttable; - -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('disttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('disttable'); -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - --- Delete all data, but keep chunks -DELETE FROM nondisttable; -DELETE FROM disttable; -VACUUM FULL ANALYZE nondisttable; -VACUUM FULL ANALYZE disttable; - -SELECT pg_table_size('disttable'), pg_relation_size('disttable'), pg_indexes_size('disttable'), pg_total_relation_size('disttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch) -FROM show_chunks('disttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('disttable'); -SELECT * FROM show_chunks('disttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; -SELECT pg_table_size('nondisttable'), pg_relation_size('nondisttable'), pg_indexes_size('nondisttable'), pg_total_relation_size('nondisttable'); -SELECT pg_table_size(ch), pg_relation_size(ch), pg_indexes_size(ch), pg_total_relation_size(ch) -FROM show_chunks('nondisttable') ch; -SELECT * FROM _timescaledb_functions.relation_size('nondisttable'); -SELECT * FROM show_chunks('nondisttable') ch JOIN LATERAL _timescaledb_functions.relation_size(ch) ON TRUE; - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - --- Test size functions on non-empty hypertable -INSERT INTO nondisttable VALUES - ('2017-01-01 06:01', 1, 1.1), - ('2017-01-01 08:01', 1, 1.2), - ('2018-01-02 08:01', 2, 1.3), - ('2019-01-01 09:11', 3, 2.1), - ('2017-01-01 06:05', 1, 1.4); -INSERT INTO disttable SELECT * FROM nondisttable; - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - --- Enable compression -ALTER TABLE nondisttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); - -ALTER TABLE disttable -SET (timescaledb.compress, - timescaledb.compress_segmentby='device', - timescaledb.compress_orderby = 'time DESC'); - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - --- Compress two chunks (out of three) to see effect of compression -SELECT compress_chunk(ch) -FROM show_chunks('disttable') ch -LIMIT 2; - -SELECT compress_chunk(ch) -FROM show_chunks('nondisttable') ch -LIMIT 2; - -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - --- Make sure functions work for non-superuser -CREATE TABLE size_test_table (value int); -INSERT INTO size_test_table SELECT * FROM generate_series(0, 10000); - -SET ROLE :ROLE_1; - --- No query permissions -\set ON_ERROR_STOP 0 -SELECT count(*) FROM disttable; -SELECT count(*) FROM size_test_table; -\set ON_ERROR_STOP 1 - --- Size functions work anyway, similar to pg_table_size, et al. --- pg_table_size() can vary with platform so not outputting -SELECT 1 FROM pg_table_size('size_test_table'); -SELECT 1 FROM pg_table_size('disttable'); -SELECT 1 FROM pg_table_size('nondisttable'); -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; -SELECT * FROM chunks_detailed_size('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunks_detailed_size('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_compression_stats('disttable') ORDER BY node_name; -SELECT * FROM hypertable_compression_stats('nondisttable') ORDER BY node_name; -SELECT * FROM chunk_compression_stats('disttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM chunk_compression_stats('nondisttable') ORDER BY chunk_schema, chunk_name, node_name; -SELECT * FROM hypertable_index_size('disttable_pkey'); -SELECT * FROM hypertable_index_size('nondisttable_pkey'); - -RESET ROLE; -GRANT SELECT ON disttable TO :ROLE_1; -GRANT SELECT ON nondisttable TO :ROLE_1; - -SET ROLE :ROLE_1; --- Querying should now work -SELECT count(*) FROM disttable; - --- hypertable_size should work now with SELECT privilege on tables -SELECT * FROM hypertable_size('disttable'); -SELECT * FROM hypertable_size('nondisttable'); -SELECT * FROM hypertable_detailed_size('disttable') ORDER BY node_name; -SELECT * FROM hypertable_detailed_size('nondisttable') ORDER BY node_name; - --- Make sure timescaledb.ssl_dir and passfile gucs can be read by a non-superuser -\c :TEST_DBNAME :ROLE_1 -\unset ECHO -\o /dev/null -SHOW timescaledb.ssl_dir; -SHOW timescaledb.passfile; -\o -\set ECHO all -\set ON_ERROR_STOP 0 -SET timescaledb.ssl_dir TO 'ssldir'; -SET timescaledb.passfile TO 'passfile'; -\set ON_ERROR_STOP 1 - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -SET client_min_messages TO ERROR; -DROP DATABASE backend_1_1 WITH (FORCE); -DROP DATABASE backend_x_2 WITH (FORCE); -DROP DATABASE backend_2_1 WITH (FORCE); -DROP DATABASE frontend_1 WITH (FORCE); -DROP DATABASE frontend_2 WITH (FORCE); diff --git a/tsl/test/sql/dist_views.sql.in b/tsl/test/sql/dist_views.sql.in deleted file mode 100644 index 22b74e2252d..00000000000 --- a/tsl/test/sql/dist_views.sql.in +++ /dev/null @@ -1,107 +0,0 @@ --- 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. - ---------------------------------------------------- --- Test views and size_utils functions on distributed hypertable ---------------------------------------------------- -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET client_min_messages TO NOTICE; -SET ROLE :ROLE_1; -SELECT setseed(1); - -CREATE TABLE dist_table(time timestamptz NOT NULL, device int, temp float, timedim date NOT NULL); -SELECT create_distributed_hypertable('dist_table', 'time', 'device', replication_factor => 2); -SELECT add_dimension('dist_table', 'timedim', chunk_time_interval=>'7 days'::interval); -INSERT INTO dist_table SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 80, '2020-01-01' -FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-04 1:00', '1 hour') t; -ALTER TABLE dist_table SET (timescaledb.compress, timescaledb.compress_segmentby='device', timescaledb.compress_orderby = 'time DESC'); - --- Test views with compression -BEGIN; -SELECT compress_chunk(chunk) -FROM show_chunks('dist_table') AS chunk -ORDER BY chunk -LIMIT 1; - -SELECT * FROM timescaledb_information.hypertables -WHERE hypertable_name = 'dist_table'; -SELECT hypertable_schema, - hypertable_name, - chunk_schema, - chunk_name, - primary_dimension, - primary_dimension_type, - range_start, - range_end, - range_start_integer, - range_end_integer, - is_compressed, - chunk_tablespace, - data_nodes -FROM timescaledb_information.chunks -ORDER BY hypertable_name, chunk_name; -SELECT * from timescaledb_information.dimensions -ORDER BY hypertable_name, dimension_number; - -SELECT * FROM chunks_detailed_size('dist_table'::regclass) -ORDER BY chunk_name, node_name; -SELECT * FROM hypertable_detailed_size('dist_table'::regclass) -ORDER BY node_name;; - ----tables with special characters in the name ---- -CREATE TABLE "quote'tab" ( a timestamp, b integer); -SELECT create_distributed_hypertable( '"quote''tab"', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -INSERT into "quote'tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"quote''tab"') ORDER BY chunk_name, node_name; - -CREATE TABLE "special#tab" ( a timestamp, b integer); -SELECT create_hypertable( 'special#tab', 'a', 'b', replication_factor=>2, chunk_time_interval=>INTERVAL '1 day'); -INSERT into "special#tab" select generate_series( '2020-02-02 10:00', '2020-02-05 10:00' , '1 day'::interval), 10; -SELECT * FROM chunks_detailed_size( '"special#tab"') ORDER BY chunk_name, node_name; -SELECT * FROM hypertable_index_size( 'dist_table_time_idx') ; - --- Test chunk_replication_status view -SELECT * FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 4; - --- drop one chunk replica -SELECT _timescaledb_functions.chunk_drop_replica(format('%I.%I', chunk_schema, chunk_name)::regclass, replica_nodes[1]) -FROM timescaledb_experimental.chunk_replication_status -ORDER BY chunk_schema, chunk_name -LIMIT 1; - -SELECT * FROM timescaledb_experimental.chunk_replication_status -WHERE num_replicas < desired_num_replicas -ORDER BY chunk_schema, chunk_name; - --- Example usage of finding data nodes to copy/move chunks between -SELECT - format('%I.%I', chunk_schema, chunk_name)::regclass AS chunk, - replica_nodes[1] AS copy_from_node, - non_replica_nodes[1] AS copy_to_node -FROM - timescaledb_experimental.chunk_replication_status -WHERE - num_replicas < desired_num_replicas -ORDER BY - chunk_schema, chunk_name; - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); - diff --git a/tsl/test/sql/include/data_fetcher_fdw_settings.sql b/tsl/test/sql/include/data_fetcher_fdw_settings.sql deleted file mode 100644 index 85c12ca354a..00000000000 --- a/tsl/test/sql/include/data_fetcher_fdw_settings.sql +++ /dev/null @@ -1,28 +0,0 @@ --- 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. - --- Default settings -EXPLAIN (COSTS) SELECT * FROM one_batch; - --- Set custom startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_startup_cost '200'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - --- Set custom tuple cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (ADD fdw_tuple_cost '2'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - --- Update startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET fdw_startup_cost '2'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - --- Update startup cost -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (SET fdw_tuple_cost '0.5'); -EXPLAIN (COSTS) SELECT * FROM one_batch; - --- Reset custom settings -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP fdw_startup_cost); -ALTER FOREIGN DATA WRAPPER timescaledb_fdw OPTIONS (DROP fdw_tuple_cost); -EXPLAIN (COSTS) SELECT * FROM one_batch; - diff --git a/tsl/test/sql/include/data_fetcher_run.sql b/tsl/test/sql/include/data_fetcher_run.sql deleted file mode 100644 index 4855b7f962e..00000000000 --- a/tsl/test/sql/include/data_fetcher_run.sql +++ /dev/null @@ -1,19 +0,0 @@ --- 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. - -ANALYZE disttable; - -SELECT count(*) FROM disttable; - -SELECT time_bucket('1 hour', time) AS time, device, avg(temp) -FROM disttable -GROUP BY 1,2 -ORDER BY 1,2; - --- Test for #5323 - ensure that no NULL tuples are generated --- if the last element of the batch is the file trailer. -SELECT count(*), count(value) FROM one_batch; - -SELECT count(*), count(value) FROM one_batch_default; - diff --git a/tsl/test/sql/include/dist_query_load.sql b/tsl/test/sql/include/dist_query_load.sql deleted file mode 100644 index ca6052e3697..00000000000 --- a/tsl/test/sql/include/dist_query_load.sql +++ /dev/null @@ -1,86 +0,0 @@ --- 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. - -\ir debugsupport.sql - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO :ROLE_1; - -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - --- Create a "normal" PG table as reference, one two-dimensional --- distributed hypertable, and a one-dimensional distributed --- hypertable -CREATE TABLE reference (time timestamptz NOT NULL, device int, location int, temp float); -CREATE TABLE hyper (LIKE reference); -CREATE TABLE hyper1d (LIKE reference); -SELECT create_distributed_hypertable('hyper', 'time', 'device', 3, - chunk_time_interval => interval '18 hours'); - -SELECT create_distributed_hypertable('hyper1d', 'time', chunk_time_interval => interval '36 hours'); - -SELECT setseed(1); -INSERT INTO reference -SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, (random() * 20)::int, random() * 80 -FROM generate_series('2019-01-01'::timestamptz, '2019-01-04'::timestamptz, '1 minute') as t; - --- Insert the same data into the hypertable but repartition the data --- set so that we can test the "safeness" of some push-downs across --- the repartitioning boundary. - -INSERT INTO hyper -SELECT * FROM reference -WHERE time < '2019-01-02 05:10'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 2); -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-02 05:10'::timestamptz -AND time < '2019-01-03 01:22'::timestamptz -ORDER BY time; -SELECT * FROM set_number_partitions('hyper', 5); -INSERT INTO hyper -SELECT * FROM reference -WHERE time >= '2019-01-03 01:22'::timestamptz -ORDER BY time; - -INSERT INTO hyper1d -SELECT * FROM reference ORDER BY time; - -SELECT d.hypertable_id, d.id, ds.range_start, ds.range_end -FROM _timescaledb_catalog.dimension d, _timescaledb_catalog.dimension_slice ds -WHERE num_slices IS NOT NULL -AND d.id = ds.dimension_id -ORDER BY 1, 2, 3, 4; - --- Set the max time we can query without hitting the repartitioned --- chunks. Note that this is before the given repartitioning time --- above because chunk boundaries do not align exactly with the given --- timestamp -\set REPARTITIONED_TIME_RANGE 'time >= ''2019-01-01''' -\set CLEAN_PARTITIONING_TIME_RANGE 'time BETWEEN ''2019-01-01'' AND ''2019-01-01 15:00''' - - --- Custom agg func for push down tests -CREATE AGGREGATE custom_sum(int4) ( - SFUNC = int4_sum, - STYPE = int8 -); - --- Set seed on all data nodes for ANALYZE to sample consistently -CALL distributed_exec($$ SELECT setseed(1); $$); -ANALYZE reference; -ANALYZE hyper; -ANALYZE hyper1d; diff --git a/tsl/test/sql/include/dist_query_run.sql b/tsl/test/sql/include/dist_query_run.sql deleted file mode 100644 index 7e8db415a15..00000000000 --- a/tsl/test/sql/include/dist_query_run.sql +++ /dev/null @@ -1,325 +0,0 @@ --- 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. - -\echo '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%' -\echo '%%% RUNNING TESTS on table:' :TABLE_NAME -\echo '%%% PREFIX:' :PREFIX -\echo '%%% WHERE_CLAUSE:' :WHERE_CLAUSE -\echo '%%% ORDER_BY_1:' :ORDER_BY_1 -\echo '%%% ORDER_BY_1_2:' :ORDER_BY_1_2 -\echo '%%% LIMIT:' :LIMIT -\echo '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%' -SELECT setseed(1); - ------------------------------------------------------------------ --- GROUP on time (partial aggregation) ------------------------------------------------------------------ -\set TEST_DESC '\n######### Grouping on time only (partial aggregation)\n' -\qecho :TEST_DESC -:PREFIX -SELECT time, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1 -:ORDER_BY_1 -:LIMIT -:OUTPUT_CMD - - -\qecho :TEST_DESC -:PREFIX -SELECT time_bucket('2 days', time) AS time, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1 -:ORDER_BY_1 -:LIMIT -:OUTPUT_CMD - ------------------------------------------------------------------ --- GROUP on time/time_bucket,device (full aggregation) ------------------------------------------------------------------ -\set TEST_DESC '\n######### Grouping on time and device (full aggregation)\n' -\qecho :TEST_DESC -:PREFIX -SELECT time, device, avg(temp) -FROM hyper -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT date_trunc('month', time) AS time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC --- HAVING clause with no aggregates. Should be reduced to a simple --- filter on the remote node. -:PREFIX -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -HAVING device > 4 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - --- HAVING clause with aggregates. In case of partial aggregation, the --- max(temp) agg should be pulled up into the target list for --- partialization. The avg(temp) is already there, so should not be --- pulled up again. -:PREFIX -SELECT time_bucket('2 days', time) AS time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -HAVING avg(temp) > 40 AND max(temp) < 70 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - ------------------------------------------------------------------ --- GROUP on device (full aggregation) ------------------------------------------------------------------ -\set TEST_DESC '\n######### Grouping on device only (full aggregation)\n' -\qecho :TEST_DESC -:PREFIX -SELECT device, avg(temp) -FROM hyper -WHERE :WHERE_CLAUSE -GROUP BY 1 -:ORDER_BY_1 -:LIMIT -:OUTPUT_CMD - ------------------------------------------------------------------ --- No push downs or some expressions not pushed down. Note that the --- qual with random() effectively filters no tuples in order to make --- this test deterministic in the output between settings. ------------------------------------------------------------------ -\set TEST_DESC '\n######### No push down on some functions\n' -\qecho :TEST_DESC -:PREFIX -SELECT location, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE AND (temp * random() >= 0) -GROUP BY 1 -:ORDER_BY_1 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT time_bucket('2 days', time) AS time, device, avg(temp), sum(temp * (random() <= 1)::int) as sum -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -HAVING avg(temp) * custom_sum(device) > 0.8 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT time, device, avg(temp), custom_sum(device) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -:ORDER_BY_1_2 -:LIMIT -:OUTPUT_CMD - ------------------------------------------------------------------ --- Test constification and runtime push down of time-related --- functions. ------------------------------------------------------------------ -\set TEST_DESC '\n######### Constification and runtime push down of time-related functions\n' -\qecho :TEST_DESC -SELECT test.tsl_override_current_timestamptz('2018-06-01 00:00'::timestamptz); - -:PREFIX -SELECT time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1, 2 -:ORDER_BY_1_2 -:LIMIT; - --- Verify that repeated runs of the same plan will get different timestamps -SELECT format('%s_stmt', :'TABLE_NAME') -AS prepared_stmt -\gset - -PREPARE :prepared_stmt AS -SELECT time, device, avg(temp) -FROM :TABLE_NAME -WHERE :WHERE_CLAUSE -GROUP BY 1, 2 -:ORDER_BY_1_2 -:LIMIT; - -:PREFIX -EXECUTE :prepared_stmt; -SELECT test.tsl_override_current_timestamptz('2019-10-15 00:00'::timestamptz); - -:PREFIX -EXECUTE :prepared_stmt; - -DEALLOCATE :prepared_stmt; - ------------------------------------------------------------------ --- LIMIT push down support ------------------------------------------------------------------ -\set TEST_DESC '\n######### LIMIT push down cases\n' - --- Basic query (should be pushed) -\qecho :TEST_DESC -:PREFIX -SELECT time, device -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10 -:OUTPUT_CMD - --- LIMIT with OFFSET -\qecho :TEST_DESC -:PREFIX -SELECT time, device -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 5 -OFFSET 5 -:OUTPUT_CMD - --- LIMIT 0 corner case (will be translated to 1) -\qecho :TEST_DESC -:PREFIX -SELECT time, device -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 0 -:OUTPUT_CMD - --- LIMIT expr that could be constified safely -\qecho :TEST_DESC -:PREFIX -SELECT time, device -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT extract(year from date '2000-01-01') -:OUTPUT_CMD - --- No push downs for some LIMIT corner cases - --- LIMIT volatile expression -\qecho :TEST_DESC -:PREFIX -SELECT time, device -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT greatest(random(), 10.0) -:OUTPUT_CMD - --- Window function -\qecho :TEST_DESC -:PREFIX -SELECT time, device, avg(temp) OVER (PARTITION BY device) -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10 -:OUTPUT_CMD - --- Ensure that using DISTINCT and DISTINCT ON prevent LIMIT push down -\qecho :TEST_DESC -:PREFIX -SELECT DISTINCT device, time -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10 -:OUTPUT_CMD - -\qecho :TEST_DESC -:PREFIX -SELECT DISTINCT ON (device) device, time -FROM :TABLE_NAME -:ORDER_BY_1_2 -LIMIT 10 -:OUTPUT_CMD - --- JOIN with a local table -CREATE TABLE join_test (device int); - -\qecho :TEST_DESC -:PREFIX -SELECT t.time -FROM :TABLE_NAME t, join_test -WHERE t.device = join_test.device -LIMIT 10; - -DROP TABLE join_test; - ------------------------------------------------------------------ --- Test CTE / sub-queries. Data from two sub-queries on the same data --- node is joined on the access node. ------------------------------------------------------------------ -\set TEST_DESC '\n######### CTEs/Sub-queries\n' - --- CTE / subquery -\qecho :TEST_DESC -:PREFIX -WITH top_n AS ( - SELECT device, avg(temp) - FROM :TABLE_NAME - WHERE :WHERE_CLAUSE - GROUP BY 1 - ORDER BY 2 DESC - LIMIT 10 -) -SELECT time_bucket('60s', time) AS "time", device, avg(temp) -FROM :TABLE_NAME INNER JOIN top_n USING (device) -WHERE :WHERE_CLAUSE -GROUP BY 1,2 -ORDER BY 1,2 -:OUTPUT_CMD - --- Join between two distributed hypertables -\qecho :TEST_DESC -:PREFIX -SELECT time_bucket('60s', h1.time) AS "time", h1.device, avg(h1.temp), max(h2.temp) -FROM hyper h1 INNER JOIN hyper1d h2 ON (time_bucket('60', h1.time) = time_bucket('60', h2.time) AND h1.device = h2.device) -WHERE h1.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' AND - h2.time BETWEEN '2019-01-01' AND '2019-01-01 15:00' -GROUP BY 1,2 -ORDER BY 1,2 -:OUTPUT_CMD - diff --git a/tsl/test/sql/include/dist_remote_error_setup.sql b/tsl/test/sql/include/dist_remote_error_setup.sql deleted file mode 100644 index ac51d8d289a..00000000000 --- a/tsl/test/sql/include/dist_remote_error_setup.sql +++ /dev/null @@ -1,122 +0,0 @@ --- 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. - --- bs is for "broken send", the type is int4 -create type bs; - -create or replace function bssend(bs) returns bytea - as :MODULE_PATHNAME, 'ts_debug_broken_int4send' - language c immutable strict parallel safe; - -create or replace function bsrecv(internal) returns bs as 'int4recv' language internal; - -create or replace function bsin(cstring) returns bs as 'int4in' language internal; - -create or replace function bsout(bs) returns cstring as 'int4out' language internal; - -create type bs(input = bsin, output = bsout, send = bssend, receive = bsrecv, - internallength = 4, passedbyvalue = true); - -create cast (int4 as bs) without function as implicit; - -create cast (bs as int4) without function as implicit; - --- same but for broken recv -create type br; - -create or replace function brsend(br) returns bytea as 'int4send' language internal; - -create or replace function brrecv(internal) returns br - as :MODULE_PATHNAME, 'ts_debug_broken_int4recv' - language c immutable strict parallel safe; - -create or replace function brin(cstring) returns br as 'int4in' language internal; - -create or replace function brout(br) returns cstring as 'int4out' language internal; - -create type br(input = brin, output = brout, send = brsend, receive = brrecv, - internallength = 4, passedbyvalue = true); - -create cast (int4 as br) without function as implicit; - -create cast (br as int4) without function as implicit; - --- recv that sleeps, optionally (want that only on one data node) -create type sr; - -create or replace function srsend(sr) returns bytea as 'int4send' language internal; - -\if :{?sleepy_sendrecv} -create or replace function srrecv(internal) returns sr - as :MODULE_PATHNAME, 'ts_debug_sleepy_int4recv' - language c immutable strict parallel safe; -\else -create or replace function srrecv(internal) returns sr as 'int4recv' language internal; -\endif - -create or replace function srin(cstring) returns sr as 'int4in' language internal; - -create or replace function srout(sr) returns cstring as 'int4out' language internal; - -create type sr(input = srin, output = srout, send = srsend, receive = srrecv, - internallength = 4, passedbyvalue = true); - -create cast (int4 as sr) without function as implicit; - -create cast (sr as int4) without function as implicit; - --- send that sleeps, optionally (want that only on one data node) -create type ss; - -create or replace function ssrecv(internal) returns ss as 'int4recv' language internal; - -\if :{?sleepy_sendrecv} -create or replace function sssend(ss) returns bytea - as :MODULE_PATHNAME, 'ts_debug_sleepy_int4send' - language c immutable strict parallel safe; -\else -create or replace function sssend(ss) returns bytea as 'int4send' language internal; -\endif - -create or replace function ssin(cstring) returns ss as 'int4in' language internal; - -create or replace function ssout(ss) returns cstring as 'int4out' language internal; - -create type ss(input = ssin, output = ssout, send = sssend, receive = ssrecv, - internallength = 4, passedbyvalue = true); - -create cast (int4 as ss) without function as implicit; - -create cast (ss as int4) without function as implicit; - --- int4out that sometimes outputs not an int (name is abbreviation of Incorrect Out) -create type io; - -create or replace function iorecv(internal) returns io as 'int4recv' language internal; - -create or replace function iosend(io) returns bytea as 'int4send' language internal; - -create or replace function ioin(cstring) returns io as 'int4in' language internal; - -create or replace function ioout(io) returns cstring - as :MODULE_PATHNAME, 'ts_debug_incorrect_int4out' - language c immutable strict parallel safe; - -create type io(input = ioin, output = ioout, send = iosend, receive = iorecv, - internallength = 4, passedbyvalue = true); - -create cast (int4 as io) without function as implicit; - -create cast (io as int4) without function as implicit; - - --- Create a function that raises an error every nth row. --- It's stable, takes a second argument and returns current number of rows, --- so that it is shipped to data nodes and not optimized out. -create or replace function ts_debug_shippable_error_after_n_rows(integer, anyelement) - returns integer as :MODULE_PATHNAME language C stable strict; - --- Same as above, but fatal. -create or replace function ts_debug_shippable_fatal_after_n_rows(integer, anyelement) - returns integer as :MODULE_PATHNAME language C stable strict; diff --git a/tsl/test/sql/include/remote_exec.sql b/tsl/test/sql/include/remote_exec.sql deleted file mode 100644 index ad2fa812a19..00000000000 --- a/tsl/test/sql/include/remote_exec.sql +++ /dev/null @@ -1,16 +0,0 @@ --- 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. - -CREATE SCHEMA IF NOT EXISTS test; -GRANT USAGE ON SCHEMA test TO PUBLIC; - -CREATE OR REPLACE FUNCTION test.remote_exec(srv_name name[], command text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION test.remote_exec_get_result_strings(srv_name name[], command text) -RETURNS TABLE("table_record" CSTRING[]) -AS :TSL_MODULE_PATHNAME, 'ts_remote_exec_get_result_strings' -LANGUAGE C; diff --git a/tsl/test/sql/remote_connection.sql b/tsl/test/sql/remote_connection.sql deleted file mode 100644 index 01c2eb79242..00000000000 --- a/tsl/test/sql/remote_connection.sql +++ /dev/null @@ -1,70 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER - -CREATE FUNCTION test.remote_connection_tests() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_connection' -LANGUAGE C STRICT; - -CREATE FUNCTION test.remote_async_tests() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_async' -LANGUAGE C STRICT; - -CREATE FUNCTION test.send_remote_query_that_generates_exception() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_bad_remote_query' -LANGUAGE C STRICT; - -CREATE FUNCTION test.get_connection_stats() -RETURNS TABLE(connections_created bigint, connections_closed bigint, results_created bigint, results_cleared bigint) -AS :TSL_MODULE_PATHNAME, 'ts_test_get_connection_stats' -LANGUAGE C STRICT; - --- =================================================================== --- create tables --- =================================================================== - -CREATE SCHEMA "S 1"; -CREATE TABLE "S 1"."T 1" ( - "C 1" int NOT NULL, - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10), - CONSTRAINT t1_pkey PRIMARY KEY ("C 1") -); - -ANALYZE "S 1"."T 1"; - -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10 - FROM generate_series(1, 1000) id; - --- =================================================================== --- run tests --- =================================================================== - -\set VERBOSITY verbose -SELECT * FROM test.get_connection_stats(); -\set ON_ERROR_STOP 0 -SELECT test.send_remote_query_that_generates_exception(); -\set ON_ERROR_STOP 1 -SELECT * FROM test.get_connection_stats(); - -SELECT test.remote_connection_tests(); -SET client_min_messages TO ERROR; -SELECT test.remote_async_tests(); - -\echo 'End Of Test' diff --git a/tsl/test/sql/remote_connection_cache.sql b/tsl/test/sql/remote_connection_cache.sql deleted file mode 100644 index 48ef85a0095..00000000000 --- a/tsl/test/sql/remote_connection_cache.sql +++ /dev/null @@ -1,60 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER - -\set DN_DBNAME_1 :TEST_DBNAME _1 -\set DN_DBNAME_2 :TEST_DBNAME _2 - -CREATE FUNCTION _timescaledb_internal.test_remote_connection_cache() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_connection_cache' -LANGUAGE C STRICT; - -CREATE FUNCTION _timescaledb_internal.test_alter_data_node(node_name NAME) -RETURNS BOOL -AS :TSL_MODULE_PATHNAME, 'ts_test_alter_data_node' -LANGUAGE C STRICT; - -SET client_min_messages TO WARNING; -SELECT node_name, database, node_created, extension_created -FROM add_data_node('loopback_1', host => 'localhost', database => :'DN_DBNAME_1', - port => current_setting('port')::int); -SELECT node_name, database, node_created, extension_created -FROM add_data_node('loopback_2', host => 'localhost', database => :'DN_DBNAME_2', - port => current_setting('port')::int); -SET client_min_messages TO INFO; - -SELECT _timescaledb_internal.test_remote_connection_cache(); - --- Test that connection cache entries for a role gets invalidated when --- we rename the role -GRANT USAGE ON FOREIGN SERVER loopback_1, loopback_2 TO :ROLE_1; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET ROLE :ROLE_1; - -CREATE TABLE testtable (time timestamptz, location int, temp float); -SELECT * FROM create_distributed_hypertable('testtable', 'time', 'location'); -INSERT INTO testtable VALUES ('2021-09-19', 1, 13.2); - --- Should show valid connections for ROLE_1 -SELECT node_name, user_name, invalidated -FROM _timescaledb_functions.show_connection_cache() -WHERE user_name=:'ROLE_1' -ORDER BY 1,2; -RESET ROLE; -BEGIN; - --- Renaming the role should invalidate the connection cache entries --- for ROLE_1/bob. The connections will be recreated on next cache --- fetch. -ALTER ROLE :ROLE_1 RENAME TO bob; -SELECT node_name, user_name, invalidated -FROM _timescaledb_functions.show_connection_cache() -WHERE user_name='bob' -ORDER BY 1,2; -ROLLBACK; - -DROP DATABASE :DN_DBNAME_1 WITH (FORCE); -DROP DATABASE :DN_DBNAME_2 WITH (FORCE); diff --git a/tsl/test/sql/remote_copy.sql b/tsl/test/sql/remote_copy.sql deleted file mode 100644 index 983bb965265..00000000000 --- a/tsl/test/sql/remote_copy.sql +++ /dev/null @@ -1,296 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_CLUSTER_SUPERUSER; - -\set DATA_NODE_1 :TEST_DBNAME _1 -\set DATA_NODE_2 :TEST_DBNAME _2 -\set DATA_NODE_3 :TEST_DBNAME _3 - --- Add data nodes using the TimescaleDB node management API -SELECT node_name, database, node_created, database_created, extension_created -FROM ( - SELECT (add_data_node(name, host => 'localhost', DATABASE => name)).* - FROM (VALUES (:'DATA_NODE_1'), (:'DATA_NODE_2'), (:'DATA_NODE_3')) v(name) -) a; -GRANT USAGE ON FOREIGN SERVER :DATA_NODE_1, :DATA_NODE_2, :DATA_NODE_3 TO PUBLIC; -GRANT CREATE ON SCHEMA public TO :ROLE_1; -SET timescaledb.hide_data_node_name_in_errors = 'on'; - --- Start out testing text copy code -SET timescaledb.enable_connection_binary_data=false; - -SET ROLE :ROLE_1; - --- Use some horrible names to make sure the parsing code works -CREATE TABLE "+ri(k33_')" ( - "thyme" bigint NOT NULL, - "))_" double precision NOT NULL, - "flavor" text DEFAULT 'mint', - "pH" float DEFAULT 7.0, - optional text -); - -SELECT create_hypertable('"+ri(k33_'')"', 'thyme', partitioning_column=>'pH', number_partitions=>4, chunk_time_interval => 100, replication_factor => 2); - --- Use local table as an etalon -create table copy_local(like "+ri(k33_')"); - -COPY copy_local FROM STDIN; -1 11 strawberry 2.3 stuff -\. - -\copy copy_local("pH", "))_", thyme) fROm stdIN deLIMitER '-'; -.01-40-208 -10.-37-315 -\. - -cOpy copy_local(thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -15,1,403,\N -203,1.0,3.21321,something like lemon -333,1.00,2309424231, _''garbled*(#\\)@#$*) -\. - -COPY copy_local FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -120321,4.4324424324254352345345,``,0,empties -4201,3333333333333333333333333333,"",1.0000000000000000000000000000000001,`empties` -342,4324,"empties",4,\N -\. - -select * from copy_local order by 1; - --- Run some successful copies -COPY "+ri(k33_')" FROM STDIN; -1 11 strawberry 2.3 stuff -\. - -\copy public . "+ri(k33_')" ("pH", "))_" , thyme) fROm stdIN deLIMitER '-'; -.01-40-208 -10.-37-315 -\. - -cOpy public."+ri(k33_')" (thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -15,1,403,\N -203,1.0,3.21321,something like lemon -333,1.00,2309424231, _''garbled*(#\\)@#$*) -\. - -COPY "+ri(k33_')" FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FREEZE, FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -120321,4.4324424324254352345345,``,0,empties -4201,3333333333333333333333333333,"",1.0000000000000000000000000000000001,`empties` -342,4324,"empties",4,\N -\. - -select * from copy_local order by 1; - --- Run some error cases -\set ON_ERROR_STOP 0 - --- Bad input -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -1,white,blue,grey,teal -\. - --- Missing paritioning column -COPY "+ri(k33_')" (thYme, "))_", "flavor") FROM STDIN; -1234,\N,resentment -\. - --- Missing required column, these generate a WARNING with a transaction id in them (too flimsy to output) -SET client_min_messages TO ERROR; -COPY "+ri(k33_')" (thyme, flavor, "pH") FROM STDIN WITH DELIMITER ','; -5,blue,2.0 -\. -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -5,\N,blue,1,blah -\. -SET client_min_messages TO INFO; - --- Invalid data after new chunk creation, data and chunks should be rolled back -COPY "+ri(k33_')" FROM STDIN WITH DELIMITER ','; -700,7,neopolitan,7,seven -800,8,pesto,8,eight -900,9,salami,9,nine -1000,white,blue,ten,hi -\. - -\set ON_ERROR_STOP 1 - --- Now do some testing of the binary frontend/backend path. -SET timescaledb.enable_connection_binary_data=true; - -COPY "+ri(k33_')" FROM STDIN; -10 11 strawberry 12.3 stuff -\. - -\copy public . "+ri(k33_')" ("pH", "))_" , thyme) fROm stdIN deLIMitER '-'; -.001-40-2080 -100.-37-3150 -\. - -cOpy public."+ri(k33_')" (thYme, "pH", "))_", "flavor") FrOm -StDiN wiTH dElImITeR ',' -; -150,10,403,\N -2030,10.0,3.21321,something like lemon -3330,10.00,2309424231, _''garbled*(#\\)@#$*) -\. - -COPY "+ri(k33_')" FROM STDIN (FORCE_NULL (flavor, "))_"), QUOTE '`', FREEZE, FORMAT csv, NULL 'empties', FORCE_NOT_NULL ("pH", "thyme")); -1203210,4.4324424324254352345345,``,0,empties -42010,3333333333333333333333333333,"",1.00000000000000000000000000000000001,`empties` -3420,4324,"empties",40,\N -\. - -SELECT * FROM "+ri(k33_')" ORDER BY 1; -SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk ORDER BY 1; -SELECT * FROM _timescaledb_catalog.chunk_data_node ORDER BY 1, 3; -SELECT * FROM _timescaledb_catalog.hypertable_data_node ORDER BY 3; -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; -\c :DATA_NODE_1 -SELECT * FROM "+ri(k33_')" ORDER BY 1; -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; -\c :DATA_NODE_2 -SELECT * FROM "+ri(k33_')" ORDER BY 1; -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; -\c :DATA_NODE_3 -SELECT * FROM "+ri(k33_')" ORDER BY 1; -select * from show_chunks('"+ri(k33_'')"') ORDER BY 1; -\c :TEST_DBNAME :ROLE_SUPERUSER; -SET ROLE :ROLE_1; - -DROP TABLE "+ri(k33_')" CASCADE; - --- Some more test for escaping and quoting -set timescaledb.enable_connection_binary_data = true; -set timescaledb.dist_copy_transfer_format = 'text'; -create table escapes(t int, value text); -select create_distributed_hypertable('escapes', 't', 'value', chunk_time_interval => 100); - -\copy escapes from stdin -1 \t\b\f\n\r\t\v\\ -2 \t -3 a\nb -4 ddddd -5 \\ -7 \\N -9 end -10 "'"'" -11 '"'"' -12 ' -\. - -\copy (select * from escapes order by escapes) to stdout - --- Null values not allowed for partitioning columns -\set ON_ERROR_STOP off - -\copy escapes from stdin -6 \N -\. - -\copy escapes from program 'printf "8\n\\.\n"' - -\copy escapes from program 'printf "8\t\n\\.\n"' - -\copy (select * from escapes order by escapes) to stdout - -\set ON_ERROR_STOP on - --- Test null values. -create table null_values(t int, value text); -select create_distributed_hypertable('null_values', 't', chunk_time_interval => 100); -\copy null_values from program 'printf "6\t\\N\n8\t\n\\.\n"' -\copy (select * from null_values order by null_values) to stdout - --- CSV -\copy (select * from escapes order by escapes) to stdout with (format csv); -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.tsv'; - -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.csv' with (format csv); -truncate escapes; -\copy escapes from 'remote-copy-escapes.csv' with (format csv); -\copy (select * from escapes order by escapes) to stdout; --- Check the result with diff -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-escapes.tsv -'; - --- Different delimiter -\copy (select * from escapes order by escapes) to stdout with (format csv, delimiter '"', quote ''''); -\copy (select * from escapes order by escapes) to 'remote-copy-escapes.csv' with (format csv, delimiter '"', quote '''', null ','); -truncate escapes; -\copy escapes from 'remote-copy-escapes.csv' with (format csv, delimiter '"', quote '''', null ','); -\copy (select * from escapes order by escapes) to stdout; --- Check the result with diff -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-escapes.tsv -'; - --- Longer values -truncate table escapes; -\copy escapes from stdin -1 a -2 aa -3 aaaa -4 aaaaaaaa -5 aaaaaaaaaaaaaaaa -6 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -7 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -8 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -9 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -11 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -12 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -13 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -\. - -\copy escapes from stdin -14 \t -15 \t\t -16 \t\t\t\t -17 \t\t\t\t\t\t\t\t -18 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -19 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -20 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -21 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -22 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -23 \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t -\. - -select sum(t), sum(length(value)) from escapes; - --- Check different file encoding -truncate table escapes; -\copy escapes from stdin -1 PostgreSQL(ポストグレス キューエル)は、拡張性とSQL準拠を強調するフリーでオープンソースの関係データベース管理システム(RDBMS)である -2 Postgresとしても知られている -4 1996年に、プロジェクトはSQLのサポートを反映してPostgreSQLに改名された -\. - -\copy (select * from escapes order by escapes) to 'remote-copy-sjis.tsv' with (encoding 'SJIS'); -\copy (select * from escapes order by escapes) to 'remote-copy-utf8.tsv' with (encoding 'UTF8'); - --- Check that output encoding works at all, and the UTF8 and SJIS files are --- different. If you set SQL_ASCII as the server encoding, it just silently --- ignores the encoding options. -\set ON_ERROR_STOP 0 -\copy (select * from escapes order by escapes) to program 'diff -q -- remote-copy-utf8.tsv -' with (encoding 'SJIS'); -\set ON_ERROR_STOP 1 - -truncate escapes; - -\copy escapes from 'remote-copy-sjis.tsv' with (encoding 'SJIS'); -\copy (select * from escapes order by escapes) to program 'diff -- remote-copy-utf8.tsv -' with (encoding 'UTF8'); - -drop table null_values; -drop table escapes; - -SET ROLE :ROLE_CLUSTER_SUPERUSER; -SELECT * FROM delete_data_node(:'DATA_NODE_1'); -SELECT * FROM delete_data_node(:'DATA_NODE_2'); -SELECT * FROM delete_data_node(:'DATA_NODE_3'); -DROP DATABASE :DATA_NODE_1 WITH (FORCE); -DROP DATABASE :DATA_NODE_2 WITH (FORCE); -DROP DATABASE :DATA_NODE_3 WITH (FORCE); diff --git a/tsl/test/sql/remote_stmt_params.sql b/tsl/test/sql/remote_stmt_params.sql deleted file mode 100644 index 0621b795190..00000000000 --- a/tsl/test/sql/remote_stmt_params.sql +++ /dev/null @@ -1,17 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER - -CREATE OR REPLACE FUNCTION _timescaledb_internal.test_stmt_params_format(binary BOOL) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_stmt_params_format' -LANGUAGE C STRICT; - --- by default we use binary format -SELECT _timescaledb_internal.test_stmt_params_format(true); - -SET timescaledb.enable_connection_binary_data = false; - -SELECT _timescaledb_internal.test_stmt_params_format(false); diff --git a/tsl/test/sql/remote_txn.sql b/tsl/test/sql/remote_txn.sql deleted file mode 100644 index 6038f46d662..00000000000 --- a/tsl/test/sql/remote_txn.sql +++ /dev/null @@ -1,581 +0,0 @@ --- 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. - --- =================================================================== --- create FDW objects --- =================================================================== - -\c :TEST_DBNAME :ROLE_SUPERUSER - -\ir include/remote_exec.sql - -CREATE OR REPLACE FUNCTION remote_node_killer_set_event(text, text) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_remote_node_killer_set_event' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION test_remote_txn_persistent_record(srv_name name) -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_persistent_record' -LANGUAGE C; - --- To ensure predictability, we want to kill the remote backend when it's in --- the midst of processing the transaction. To ensure that the access node --- sets the event handler and then takes an exclusive session lock on the --- "remote_conn_xact_end" advisory lock via "debug_waitpoint_enable" function --- --- The "RegisterXactCallback" callback on the remote backend tries to take --- this same advisory lock in shared mode and waits. This allows the event --- handler enough time to kill this remote backend at the right time --- --- Don't forget to release lock via debug_waitpoint_release on the access node --- since it's a session level advisory lock --- -CREATE OR REPLACE FUNCTION add_loopback_server( - server_name NAME, - host TEXT = 'localhost', - database NAME = current_database(), - port INTEGER = inet_server_port(), - if_not_exists BOOLEAN = FALSE, - bootstrap BOOLEAN = TRUE, - password TEXT = NULL -) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME, - server_created BOOL, database_created BOOL, extension_created BOOL) -AS :TSL_MODULE_PATHNAME, 'ts_unchecked_add_data_node' -LANGUAGE C; - -SELECT server_name, database, server_created, database_created, extension_created FROM add_loopback_server('loopback', database => :'TEST_DBNAME', bootstrap => false); -SELECT server_name, database, server_created, database_created, extension_created FROM add_loopback_server('loopback2', database => :'TEST_DBNAME', bootstrap => false); - --- =================================================================== --- create objects used through FDW loopback server --- =================================================================== -CREATE SCHEMA "S 1"; -CREATE TABLE "S 1"."T 1" ( - "C 1" int NOT NULL, - c2 int NOT NULL, - c3 text, - c4 timestamptz, - c5 timestamp, - c6 varchar(10), - c7 char(10), - CONSTRAINT t1_pkey PRIMARY KEY ("C 1") -); - -ANALYZE "S 1"."T 1"; - -INSERT INTO "S 1"."T 1" - SELECT id, - id % 10, - to_char(id, 'FM00000'), - '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, - '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, - id % 10, - id % 10 - FROM generate_series(1, 1000) id; - -\set ON_ERROR_STOP 0 - -SELECT test_remote_txn_persistent_record('loopback'); - --- =================================================================== --- 1 pc tests --- =================================================================== - ---successfull transaction -SET timescaledb.enable_2pc = false; - ---initially, there are no connections in the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --expect to see one connection in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; - ---connection should remain, idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20001; - ---aborted transaction -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --existing connection, in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -ROLLBACK; - ---connection should remain, in idle state after rollback -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20002; - ---constraint violation -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; - --- Connection should remain after conflict, in idle state -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---the next few statements inject faults before the commit. They should all fail ---and be rolled back with no unresolved state --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('pre-commit', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20003,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; -RESET client_min_messages; -SELECT debug_waitpoint_release('remote_conn_xact_end'); - --- Failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20003; -SELECT count(*) FROM pg_prepared_xacts; - --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('waiting-commit', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20004,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; -RESET client_min_messages; -SELECT debug_waitpoint_release('remote_conn_xact_end'); - ---connection failed during commit, so should be cleared from the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---during waiting-commit the data node process could die before or after ---executing the commit on the remote node. So the behaviour here is non-deterministic ---this is the bad part of 1-pc transactions. ---there are no prepared txns in either case -SELECT count(*) FROM pg_prepared_xacts; - ---fail the connection before the abort -BEGIN; - SELECT remote_node_killer_set_event('pre-abort', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - --- since the error messages/warnings from this ROLLBACK varies between --- platforms/environments we remove it from test output and show --- SQLSTATE instead. SQLSTATE should be 00000 since we are not --- throwing errors during rollback/abort and it should succeed in any --- case. --- -ROLLBACK; --- -\echo 'ROLLBACK SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 20005; -SELECT count(*) FROM pg_prepared_xacts; - ---the failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---block preparing transactions on the access node -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (20006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -PREPARE TRANSACTION 'test-2'; - - --- =================================================================== --- 2 pc tests --- =================================================================== ---undo changes from 1-pc tests -DELETE FROM "S 1"."T 1" where "C 1" >= 20000; -SET timescaledb.enable_2pc = true; - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---simple commit -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; - ---connection should remain in idle state -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10001; -SELECT count(*) FROM pg_prepared_xacts; - ---simple -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (11001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - --connection in transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -ROLLBACK; - ---rolled back transaction, but connection should remain in idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 11001; -SELECT count(*) FROM pg_prepared_xacts; - ---constraint violation should fail the txn -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; - ---connection should remain in idle after constraint violation -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---the next few statements inject faults before the commit. They should all fail ---and be rolled back with no unresolved state -BEGIN; - SELECT remote_node_killer_set_event('pre-prepare-transaction', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10002,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 08006 connection_failure --- -COMMIT; --- -\echo 'COMMIT SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - ---the connection was killed, so should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10002; -SELECT count(*) FROM pg_prepared_xacts; - -BEGIN; - SELECT remote_node_killer_set_event('waiting-prepare-transaction', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10003,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 08006 connection_failure --- -COMMIT; --- -\echo 'COMMIT SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - ---the connection should be cleared from the cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10003; - ---during waiting-prepare-transaction the data node process could die before or after ---executing the prepare transaction. To be safe to either case rollback using heal_server. -SELECT count(*) FROM _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) from _timescaledb_catalog.remote_txn; - - ---the following only breaks stuff in post-commit so commit should succeed ---but leave transaction in an unresolved state. -BEGIN; - SELECT remote_node_killer_set_event('post-prepare-transaction', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10004,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion --- -COMMIT; --- -\echo 'COMMIT SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - ---connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---unresolved state shown here -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10004; -SELECT count(*) FROM pg_prepared_xacts; - ---this fails because heal cannot run inside txn block -BEGIN; - SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -COMMIT; - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -select count(*) from _timescaledb_catalog.remote_txn; - ---this resolves the previous txn -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10004; -SELECT count(*) FROM pg_prepared_xacts; ---cleanup also happened -select count(*) from _timescaledb_catalog.remote_txn; - -BEGIN; - SELECT remote_node_killer_set_event('pre-commit-prepared', 'loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10006,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion --- -COMMIT; --- -\echo 'COMMIT SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---unresolved state shown here -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10006; -SELECT count(*) FROM pg_prepared_xacts; ---this resolves the previous txn -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10006; -SELECT count(*) FROM pg_prepared_xacts; -select count(*) from _timescaledb_catalog.remote_txn; - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -BEGIN; - SELECT remote_node_killer_set_event('waiting-commit-prepared','loopback'); - SELECT debug_waitpoint_enable('remote_conn_xact_end'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10005,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); --- since the error messages/warnings from this COMMIT varies between --- platforms/environments we remove it from test output and show SQLSTATE instead. --- SQLSTATE should be 00000 successful_completion --- -COMMIT; --- -\echo 'COMMIT SQLSTATE' :SQLSTATE -SELECT debug_waitpoint_release('remote_conn_xact_end'); - ---at this point the commit prepared might or might not have been executed before ---the data node process was killed. ---but in any case, healing the server will bring it into a known state -SELECT count(*) FROM _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); - ---heal does not use the connection cache, so unaffected -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10005; -SELECT count(*) FROM pg_prepared_xacts; -select count(*) from _timescaledb_catalog.remote_txn; - ---test prepare transactions. Note that leaked prepared stmts should be ---detected by `remote_txn_check_for_leaked_prepared_statements` so we ---should be fine if we don't see any WARNINGS. -BEGIN; - SELECT test.remote_exec('{loopback}', $$ PREPARE prep_1 AS SELECT 1 $$); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; ---unique constraint violation, connection should remain -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -BEGIN; - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback}', $$ PREPARE prep_1 AS SELECT 1 $$); - - --connection in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - --generate a unique violation - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - - ROLLBACK TO SAVEPOINT save_1; - - --for correctness, the connection must remain after rollback since - --the transaction is still ongoing - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (81,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; - ---connection should remain and be idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 81; - - ---Make the primary key DEFERRABLE and INITIALLY DEFERRED ---this is a way to force errors to happen during PREPARE TRANSACTION ---since pkey constraint violations would not occur on the INSERT command ---but rather are deferred till PREPARE TRANSACTION happens. -ALTER TABLE "S 1"."T 1" DROP CONSTRAINT t1_pkey, -ADD CONSTRAINT t1_pkey PRIMARY KEY ("C 1") DEFERRABLE INITIALLY DEFERRED; - ---test ROLLBACK TRANSACTION on failure in PREPARE TRANSACTION. --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; -RESET client_min_messages; - ---connection should be removed since PREPARE TRANSACTION failed -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM pg_prepared_xacts; - ---test ROLLBACK TRANSACTION ---this has an error on the second connection. So should force conn1 to prepare transaction ---ok and then have the txn fail on conn2. Thus conn1 would do a ROLLBACK PREPARED. ---conn2 would do a ROLLBACK TRANSACTION. --- We set min message level to "error" since order of warnings generated --- is different due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10010,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - - --Both connections in transaction state - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; -RESET client_min_messages; - ---one connection should remain and be idle -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10010; -SELECT count(*) FROM pg_prepared_xacts; - --- Below will fail the abort and thus ROLLBACK TRANSACTION will never --- be called leaving a prepared_xact that should be rolled back by --- heal server. --- --- We set min message level to "error" since different warnings can be --- generated due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('pre-abort', 'loopback'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10011,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; -RESET client_min_messages; - ---failed connection should be cleared -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10011; -SELECT count(*) FROM pg_prepared_xacts; -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" = 10011; -SELECT count(*) FROM pg_prepared_xacts; - ---heal is not using the connection cache -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ---test simple subtrans abort. -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10012,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10013,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ROLLBACK TO SAVEPOINT save_1; - - -- For correctness, both connections should remain in order to - -- continue the transaction - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10014,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10015,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -COMMIT; - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" > 10011; -SELECT count(*) FROM pg_prepared_xacts; - --- Test comm error in subtrans abort --- --- We set min message level to "error" since different warnings can be --- generated due to timing issues but check that the transaction was --- rolled back after the commit. -SET client_min_messages TO error; -BEGIN; - SELECT remote_node_killer_set_event('subxact-abort', 'loopback'); - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10017,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10018,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SAVEPOINT save_1; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10001,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - ROLLBACK TO SAVEPOINT save_1; - SELECT node_name, connection_status, transaction_status, transaction_depth, processing - FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10019,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); - SELECT test.remote_exec('{loopback2}', $$ INSERT INTO "S 1"."T 1" VALUES (10020,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -COMMIT; -RESET client_min_messages; - -SELECT node_name, connection_status, transaction_status, transaction_depth, processing -FROM _timescaledb_functions.show_connection_cache() ORDER BY 1,4; -SELECT count(*) FROM "S 1"."T 1" WHERE "C 1" > 10016; -SELECT count(*) FROM pg_prepared_xacts; - - ---block preparing transactions on the frontend -BEGIN; - SELECT test.remote_exec('{loopback}', $$ INSERT INTO "S 1"."T 1" VALUES (10051,1,'bleh', '2001-01-01', '2001-01-01', 'bleh') $$); -PREPARE TRANSACTION 'test-1'; - --- test remote_txn cleanup on data node delete --- -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback' or data_node_name = 'loopback2'; - -SELECT * FROM delete_data_node('loopback'); -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback'; - -SELECT * FROM delete_data_node('loopback2'); -SELECT count(*) FROM _timescaledb_catalog.remote_txn WHERE data_node_name = 'loopback2'; diff --git a/tsl/test/sql/remote_txn_id.sql b/tsl/test/sql/remote_txn_id.sql deleted file mode 100644 index f5626463121..00000000000 --- a/tsl/test/sql/remote_txn_id.sql +++ /dev/null @@ -1,37 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER -CREATE FUNCTION _timescaledb_functions.test_remote_txn_id() -RETURNS void -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_id' -LANGUAGE C STRICT; - -SELECT _timescaledb_functions.test_remote_txn_id(); - -SELECT 'ts-1-10-20-30'::rxid; - -create table tbl_w_rxid( - txn_id rxid -); - -CREATE UNIQUE INDEX idx_name ON tbl_w_rxid ((txn_id::text)); - -INSERT INTO tbl_w_rxid VALUES ('ts-1-10-20-30'), ('ts-1-11-20-30'), ('ts-1-10-21-30'); - -SELECT txn_id, _timescaledb_functions.rxid_in(_timescaledb_functions.rxid_out(txn_id))::text = txn_id::text FROM tbl_w_rxid; - -\set ON_ERROR_STOP 0 -INSERT INTO tbl_w_rxid VALUES ('ts-1-10-20-30'); - -SELECT ''::rxid; -SELECT '---'::rxid; -SELECT '----'::rxid; -SELECT 'ts---'::rxid; -SELECT 'ts----'::rxid; -SELECT 'ts-1-10-20a'::rxid; -SELECT 'ts-2-10-20-40'::rxid; -SELECT 'ts-1-10-20.0'::rxid; -SELECT 'ts-1-10.0-20'::rxid; -SELECT 'ts-a1-10-20-8'::rxid; diff --git a/tsl/test/sql/remote_txn_resolve.sql b/tsl/test/sql/remote_txn_resolve.sql deleted file mode 100644 index 269be8b7105..00000000000 --- a/tsl/test/sql/remote_txn_resolve.sql +++ /dev/null @@ -1,144 +0,0 @@ --- 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. - -\c :TEST_DBNAME :ROLE_SUPERUSER - -CREATE OR REPLACE FUNCTION create_records() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION create_prepared_record() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_prepared_record' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION create_records_with_concurrent_heal() -RETURNS VOID -AS :TSL_MODULE_PATHNAME, 'ts_test_remote_txn_resolve_create_records_with_concurrent_heal' -LANGUAGE C; - -CREATE OR REPLACE FUNCTION add_loopback_server( - server_name NAME, - host TEXT = 'localhost', - database NAME = current_database(), - port INTEGER = inet_server_port(), - if_not_exists BOOLEAN = FALSE, - bootstrap BOOLEAN = TRUE, - password TEXT = NULL -) RETURNS TABLE(server_name NAME, host TEXT, port INTEGER, database NAME, - server_created BOOL, database_created BOOL, extension_created BOOL) -AS :TSL_MODULE_PATHNAME, 'ts_unchecked_add_data_node' -LANGUAGE C; - -SELECT database FROM add_loopback_server('loopback', database => :'TEST_DBNAME', bootstrap => false); -SELECT database FROM add_loopback_server('loopback2', database => :'TEST_DBNAME', bootstrap => false); -SELECT database FROM add_loopback_server('loopback3', database => :'TEST_DBNAME', bootstrap => false); - -create table table_modified_by_txns ( - describes text -); - ---create records will create 3 records ---1) that is committed ---2) that is prepared but not committed ---3) that is prepared and rolled back ---Thus (1) will be seen right away, (2) will be seen after the heal, (3) will never be seen -SELECT create_records(); - -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); - -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - ---insert one record where the heal function is run concurrently during different steps of the process ---this tests safety when, for example, the heal function is run while the frontend txn is still ongoing. -SELECT create_records_with_concurrent_heal(); -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - -SELECT create_records(); --- create an additional prepared entry. This will allow us to test heal behavior when one --- attempt errors out and when the other should succeed. The debug_inject_gid_error logic --- only induces one error for now. This can be modified later as desired via another --- session variable. -SELECT create_prepared_record(); ---inject errors in the GID and test "commit" resolution for it -SET timescaledb.debug_inject_gid_error TO 'commit'; ---heal should error out and the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); ---inject errors in the GID and test "abort" resolution for it -SET timescaledb.debug_inject_gid_error TO 'abort'; ---heal should error out and the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); ---test "inprogress" resolution for the prepared 2PC -SET timescaledb.debug_inject_gid_error TO 'inprogress'; ---heal will not error out but the prepared transaction should still be visible -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - --- Again process 2 records where one errors out and other succeeds -SELECT create_prepared_record(); ---set to any random value so that it does not have any effect and allows healing -SET timescaledb.debug_inject_gid_error TO 'ignored'; -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - ---test that it is safe to have non-ts prepared-txns with heal -BEGIN; - INSERT INTO public.table_modified_by_txns VALUES ('non-ts-txn'); -PREPARE TRANSACTION 'non-ts-txn'; - -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback2')); -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback3')); - -COMMIT PREPARED 'non-ts-txn'; -SELECT * FROM table_modified_by_txns; -SELECT count(*) FROM pg_prepared_xacts; -SELECT count(*) FROM _timescaledb_catalog.remote_txn; - --- test that healing function does not conflict with other databases --- --- #3433 - --- create additional database and simulate remote txn activity -CREATE DATABASE test_an2; -\c test_an2 -BEGIN; -CREATE TABLE unused(id int); -PREPARE TRANSACTION 'ts-1-10-20-30'; -\c :TEST_DBNAME :ROLE_SUPERUSER --- should not fail -SELECT _timescaledb_functions.remote_txn_heal_data_node((SELECT OID FROM pg_foreign_server WHERE srvname = 'loopback')); -\c test_an2 -ROLLBACK PREPARED 'ts-1-10-20-30'; -\c :TEST_DBNAME :ROLE_SUPERUSER -DROP DATABASE test_an2 WITH (FORCE); diff --git a/tsl/test/t/006_job_crash_log.pl b/tsl/test/t/001_job_crash_log.pl similarity index 100% rename from tsl/test/t/006_job_crash_log.pl rename to tsl/test/t/001_job_crash_log.pl diff --git a/tsl/test/t/001_simple_multinode.pl b/tsl/test/t/001_simple_multinode.pl deleted file mode 100644 index df862a3226a..00000000000 --- a/tsl/test/t/001_simple_multinode.pl +++ /dev/null @@ -1,132 +0,0 @@ -# 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. - -# test a simple multi node cluster creation and basic operations -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 19; - -#Initialize all the multi-node instances -my $an = AccessNode->create('an'); - -my $dn1 = DataNode->create('dn1'); -my $dn2 = DataNode->create('dn2'); - -$an->add_data_node($dn1); -$an->add_data_node($dn2); - -#Create a distributed hypertable and insert a few rows -$an->safe_psql( - 'postgres', - qq[ - CREATE TABLE test(time timestamp NOT NULL, device int, temp float); - SELECT create_distributed_hypertable('test', 'time', 'device', 3); - INSERT INTO test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; - ]); - -#Check that chunks are shown appropriately on all nodes of the multi-node setup -my $query = q[SELECT * from show_chunks('test');]; - -#Query Access node -$an->psql_is( - 'postgres', $query, q[_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_4_chunk], 'AN shows correct set of chunks' -); - -#Query datanode1 -$dn1->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_1_chunk\n_timescaledb_internal._dist_hyper_1_3_chunk\n_timescaledb_internal._dist_hyper_1_4_chunk", - 'DN1 shows correct set of chunks'); - -#Query datanode2 -$dn2->psql_is( - 'postgres', $query, - "_timescaledb_internal._dist_hyper_1_2_chunk", - 'DN2 shows correct set of chunks'); - -# Check that remote parameterized queries are handled correctly via EXPLAIN -$an->safe_psql( - 'postgres', - qq[ - CREATE TABLE conditions_dist2 ( - time TIMESTAMPTZ NOT NULL, - location TEXT NOT NULL, - temperature DOUBLE PRECISION NULL, - humidity DOUBLE PRECISION NULL ); - SELECT create_distributed_hypertable('conditions_dist2', 'time', 'location'); - INSERT INTO conditions_dist2 - SELECT '2022-01-18 00:00:00' :: timestamptz + ( i || ' sec' ) :: interval, - i :: text, i, i FROM generate_series(1, 10) i; - ]); - -my ($cmdret, $stdout, $stderr) = $an->psql( - 'postgres', - qq[ - SET timescaledb.enable_remote_explain = ON; - EXPLAIN (verbose) SELECT location, RESULT.time_array, RESULT.value_array - FROM conditions_dist2 series INNER JOIN LATERAL ( - SELECT array_agg(TIME) AS time_array, array_agg(humidity) AS value_array - FROM ( - SELECT TIME, humidity AS humidity FROM conditions_dist2 metric - WHERE metric.location = series.location AND TIME >= '2022-01-18T05:58:00Z' - AND TIME <= '2022-01-19T06:01:00Z' ORDER BY TIME ) AS time_ordered_rows - ) AS RESULT ON (RESULT.value_array IS NOT NULL); - ]); - -# Check that output contains message for parameterized remote query -is($cmdret, 0); -like( - $stdout, - qr/Remote EXPLAIN: Unavailable due to parameterized query/, - 'Expected EXPLAIN output for parameterized query'); - -# Check that distributed tables in non-default schema and also containing user created types -# in another schema are created properly -$query = q[CREATE SCHEMA myschema]; -$an->safe_psql('postgres', "$query"); -$query = - q[CREATE TYPE public.full_address AS (city VARCHAR(90), street VARCHAR(90))]; -$an->safe_psql('postgres', "$query; CALL distributed_exec('$query');"); - -# Create a table in the myschema schema using this unqualified UDT. Should work -$an->safe_psql('postgres', - "CREATE TABLE myschema.test (time timestamp, a full_address);"); - -# A distributed table creation followed by sample INSERT should succeed now -$an->safe_psql('postgres', - "SELECT create_distributed_hypertable('myschema.test', 'time');"); -$an->safe_psql('postgres', - "INSERT INTO myschema.test VALUES ('2018-03-02 1:00', ('Kilimanjaro', 'Diamond St'));" -); -$an->psql_is( - 'postgres', - "SELECT * from myschema.test", - q[2018-03-02 01:00:00|(Kilimanjaro,"Diamond St")], - 'AN shows correct data with UDT from different schema'); - -# Test behavior of size utillities when a data node is not responding -$an->psql_is( - 'postgres', "SELECT * FROM hypertable_size('myschema.test')", - q[81920], 'AN hypertable_size() returns correct size'); - -$dn1->stop('fast'); -($cmdret, $stdout, $stderr) = - $an->psql('postgres', "SELECT * FROM hypertable_size('myschema.test')"); - -# Check that hypertable_size() returns error when dn1 is down -is($cmdret, 3); -like( - $stderr, - qr/ERROR: could not connect to "dn1"/, - 'failure when connecting to dn1'); - -done_testing(); - -1; diff --git a/tsl/test/t/002_chunk_copy_move.pl b/tsl/test/t/002_chunk_copy_move.pl deleted file mode 100644 index e243f59911e..00000000000 --- a/tsl/test/t/002_chunk_copy_move.pl +++ /dev/null @@ -1,297 +0,0 @@ -# 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. - -# test the multi node chunk copy/move operation end-to-end -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 287; - -#Initialize all the multi-node instances -my $an = AccessNode->create('an'); -my $dn1 = DataNode->create('dn1', allows_streaming => 'logical'); -my $dn2 = DataNode->create('dn2', allows_streaming => 'logical'); - -$an->add_data_node($dn1); -$an->add_data_node($dn2); - -$an->safe_psql('postgres', - "GRANT USAGE ON FOREIGN SERVER dn1, dn2 TO PUBLIC;"); - -for my $node ($an, $dn1, $dn2) -{ - $node->safe_psql('postgres', "CREATE ROLE htowner LOGIN"); -} -$an->safe_psql('postgres', "GRANT CREATE ON SCHEMA public TO htowner"); - -#Create few distributed hypertables with default and specified schema names and insert a few rows -$an->safe_psql( - 'postgres', - qq[ - SET ROLE htowner; - CREATE TABLE test(time timestamp NOT NULL, device int, temp float); - SELECT create_distributed_hypertable('test', 'time', 'device', 3); - INSERT INTO test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; - CREATE TABLE measurements(time TIMESTAMP NOT NULL, device INTEGER, temperature FLOAT); - SELECT * FROM create_distributed_hypertable('public.measurements', 'time', 'device', 3, associated_schema_name => 'public'); - INSERT INTO measurements SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') AS t; - ]); - -#Check that chunks are shown appropriately on all nodes of the multi-node setup -my $query = q[SELECT * from show_chunks('test');]; -my $operation_id = "ts_copy_1_1"; - -#Check chunk states before the move -check_pre_move_chunk_states(); - -#Setup the error injection function on the AN -my $extversion = $an->safe_psql('postgres', - "SELECT extversion from pg_catalog.pg_extension WHERE extname = 'timescaledb'" -); -$an->safe_psql( - 'postgres', - qq[ - CREATE OR REPLACE FUNCTION error_injection_on(TEXT) RETURNS VOID LANGUAGE C VOLATILE STRICT - AS 'timescaledb-$extversion', 'ts_debug_point_enable'; - ]); - -#Induce errors in various stages in the chunk move activity and ensure that the -#cleanup function restores things to the previous sane state - -my @stages = - qw(init create_empty_chunk create_publication create_replication_slot create_subscription sync_start sync drop_publication drop_subscription attach_chunk delete_chunk); - -my ($stdout, $stderr, $ret); -my $curr_index = 1; -my $arrSize = @stages; - -while ($curr_index < $arrSize) -{ - #Enable the error at each stage - #Call the move_chunk procedure which should error out now - #We provide the operation id ourselves - $operation_id = "ts_cloud_" . $curr_index . "_1"; - ($ret, $stdout, $stderr) = $an->psql('postgres', - "SELECT error_injection_on('$stages[$curr_index]'); SET ROLE htowner; CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> 'dn1', destination_node => 'dn2', operation_id => '$operation_id');" - ); - is($ret, 3, - "move_chunk fails as expected in stage '$stages[$curr_index]'"); - like( - $stderr, - qr/ERROR: error injected at debug point '$stages[$curr_index]'/, - 'failure in expected stage'); - - #The earlier debug error point gets released automatically since it's a session lock - #Call the cleanup procedure to make things right - $an->safe_psql('postgres', - "SET ROLE htowner; CALL timescaledb_experimental.cleanup_copy_chunk_operation(operation_id=>'$operation_id');" - ); - - #Check chunk state is as before the move - check_pre_move_chunk_states(); - - $curr_index++; -} - -#_timescaledb_catalog.chunk_copy_operation catalog should be empty due to the cleanup above -$an->psql_is( - 'postgres', "SELECT * from _timescaledb_catalog.chunk_copy_operation", - "", "AN catalog is empty as expected"); - -for my $node ($an, $dn1, $dn2) -{ - $node->safe_psql('postgres', "CREATE ROLE testrole LOGIN"); -} - -#Error out the move if user doesn't have superuser nor replication perms -($ret, $stdout, $stderr) = $an->psql('postgres', - "SET ROLE testrole; CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> 'dn1', destination_node => 'dn2')" -); - -like( - $stderr, - qr/must be superuser, replication role, or hypertable owner to copy\/move chunk to data node/, - 'Expected failure due to no credentials'); - -#Provide REPLICATION creds to this user now -for my $node ($an, $dn1, $dn2) -{ - $node->safe_psql('postgres', "ALTER ROLE testrole REPLICATION;"); -} - -#Check that the function does not segfault on NULL arguments -($ret, $stdout, $stderr) = $an->psql('postgres', - "SELECT timescaledb_experimental.subscription_exec(NULL)"); - -#Check that function errors out if any non SUBSCRIPTON command is passed to it -($ret, $stdout, $stderr) = $an->psql('postgres', - "SET ROLE testrole; SELECT timescaledb_experimental.subscription_exec('DROP ROLE testrole')" -); - -like( - $stderr, - qr/this function only accepts SUBSCRIPTION commands/, - 'Expected failure due to wrong command to function'); - -#Move chunk _timescaledb_internal._dist_hyper_1_1_chunk to DN2 from AN -#The move_chunk function when called with a REPLICATION user should work without -#granting any additional perms to it. This is because this function will internally -#assume superuser privileges to carry out the actual move operation. -$an->safe_psql('postgres', - "SET ROLE testrole; CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> 'dn1', destination_node => 'dn2')" -); - -#An entry for the above move should exist with "complete" stage in the catalog now -$an->psql_is( - 'postgres', - "SELECT operation_id, completed_stage, source_node_name, dest_node_name, delete_on_source_node from _timescaledb_catalog.chunk_copy_operation", - "ts_copy_1_1|complete|dn1|dn2|t", - "AN catalog is as expected"); - -# Cleanup with a role which doesn't have superuser, replication or ownernership should fail -$an->safe_psql('postgres', "CREATE ROLE testrole2 LOGIN;"); -($ret, $stdout, $stderr) = $an->psql('postgres', - "SET ROLE testrole2; CALL timescaledb_experimental.move_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> 'dn1', destination_node => 'dn2')" -); - -like( - $stderr, - qr/must be superuser, replication role, or hypertable owner to copy\/move chunk to data node/, - 'Expected failure due to no credentials'); -# -#Run cleanup on this operstion. It should just delete the catalog entry since the -#activity has completed successfully. Rest of the checks below should succeed -#Try this cleanup as the REPLICATION user -$an->safe_psql('postgres', - "SET ROLE testrole; CALL timescaledb_experimental.cleanup_copy_chunk_operation(operation_id=>'ts_copy_1_1');" -); -$an->psql_is( - 'postgres', "SELECT * from _timescaledb_catalog.chunk_copy_operation", - "", "AN catalog is empty as expected"); - -#Query datanode1 after the above move -$dn1->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_3_chunk\n_timescaledb_internal._dist_hyper_1_4_chunk", - 'DN1 shows correct set of chunks'); - -#Check contents on the chunk on DN2, after the move -$dn2->psql_is( - 'postgres', - "SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk", - qq[406], - "DN2 has correct contents after the move in the chunk"); - -#Query datanode2 -$dn2->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_2_chunk\n_timescaledb_internal._dist_hyper_1_1_chunk", - 'DN2 shows correct set of chunks'); - -#Copy chunk _timescaledb_internal._dist_hyper_1_1_chunk to DN1 from DN2 -$an->safe_psql('postgres', - "CALL timescaledb_experimental.copy_chunk(chunk=>'_timescaledb_internal._dist_hyper_1_1_chunk', source_node=> 'dn2', destination_node => 'dn1')" -); - -#Query datanode1 after the above copy -$dn1->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_3_chunk\n_timescaledb_internal._dist_hyper_1_4_chunk\n_timescaledb_internal._dist_hyper_1_1_chunk", - 'DN1 shows correct set of chunks after the copy'); - -#Check contents on the chunk on DN2, after the copy -$dn1->psql_is( - 'postgres', - "SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk", - qq[406], - "DN1 has correct contents after the copy in the chunk"); - -#Check contents on the chunk on DN2, after the copy -$dn2->psql_is( - 'postgres', - "SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk", - qq[406], - "DN2 has correct contents after the copy in the chunk"); - -#Query datanode2 -$dn2->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_2_chunk\n_timescaledb_internal._dist_hyper_1_1_chunk", - 'DN2 shows correct set of chunks after the copy'); - -#Test move chunk of non-default associated_schema_name. -$an->safe_psql('postgres', - "SET ROLE testrole; CALL timescaledb_experimental.move_chunk(chunk=>'public._dist_hyper_2_5_chunk', source_node=> 'dn1', destination_node => 'dn2')" -); - -#Check contents on the chunk on DN2, after the move -$dn2->psql_is( - 'postgres', "SELECT count(device) FROM public._dist_hyper_2_5_chunk", - qq[58], "DN2 has correct contents after the move in the chunk"); - -done_testing(); - -#Check the following -#1) chunk is still on "dn1", -#2) there's no entry on "dn2", -#3) there are no left over replication slots and publications on "dn1", -#4) there is no subscription on "dn2" -sub check_pre_move_chunk_states -{ - #Query Access node - $an->psql_is( - 'postgres', $query, q[_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_4_chunk], 'AN shows correct set of chunks' - ); - - #Query datanode1 - $dn1->psql_is( - 'postgres', - $query, - "_timescaledb_internal._dist_hyper_1_1_chunk\n_timescaledb_internal._dist_hyper_1_3_chunk\n_timescaledb_internal._dist_hyper_1_4_chunk", - 'DN1 shows correct set of chunks'); - - #Check contents on the chunk on DN1 - $dn1->psql_is( - 'postgres', - "SELECT sum(device) FROM _timescaledb_internal._dist_hyper_1_1_chunk", - qq[406], - "DN1 has correct contents in the chunk"); - - #Query datanode2 - $dn2->psql_is( - 'postgres', $query, - "_timescaledb_internal._dist_hyper_1_2_chunk", - 'DN2 shows correct set of chunks'); - - #Check that there is no replication slot on datanode1 - $dn1->psql_is( - 'postgres', - "SELECT 1 FROM pg_catalog.pg_replication_slots WHERE slot_name = '$operation_id'", - "", - 'DN1 doesn\'t have left over replication slots'); - - #Check that there is no publication on datanode1 - $dn1->psql_is( - 'postgres', - "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '$operation_id'", - "", - 'DN1 doesn\'t have left over publication'); - - #Check that there is no subscription on datanode2 - $dn2->psql_is( - 'postgres', - "SELECT 1 FROM pg_catalog.pg_subscription WHERE subname = '$operation_id'", - "", - 'DN2 doesn\'t have left over subscription'); -} - -1; diff --git a/tsl/test/t/009_logrepl_decomp_marker.pl b/tsl/test/t/002_logrepl_decomp_marker.pl similarity index 100% rename from tsl/test/t/009_logrepl_decomp_marker.pl rename to tsl/test/t/002_logrepl_decomp_marker.pl diff --git a/tsl/test/t/003_connections_privs.pl b/tsl/test/t/003_connections_privs.pl deleted file mode 100644 index e82a310930d..00000000000 --- a/tsl/test/t/003_connections_privs.pl +++ /dev/null @@ -1,135 +0,0 @@ -# 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. - -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 28; - -#Initialize all the multi-node instances -my $an = AccessNode->create('an'); -my $dn1 = DataNode->create('dn1'); -my $dn2 = DataNode->create('dn2'); - -$an->add_data_node($dn1); -$an->add_data_node($dn2); - -$dn1->append_conf('postgresql.conf', 'log_connections=true'); -$dn2->append_conf('postgresql.conf', 'log_connections=true'); - -$an->safe_psql( - 'postgres', - qq[ - CREATE ROLE alice; - CALL distributed_exec('CREATE ROLE alice LOGIN'); - GRANT CREATE ON SCHEMA public TO alice; - GRANT USAGE ON FOREIGN SERVER dn1,dn2 TO alice; - SET ROLE alice; - CREATE TABLE conditions (time timestamptz, location int, temp float); - SELECT create_distributed_hypertable('conditions', 'time', 'location'); - INSERT INTO conditions VALUES ('2021-09-20 00:00:00+02', 1, 23.4); - ]); - - -my ($cmdret, $stdout, $stderr) = $an->psql( - 'postgres', - qq[ - SET ROLE alice; - SELECT time AT TIME ZONE 'America/New_York', location, temp FROM conditions; - SELECT node_name, user_name, invalidated - FROM _timescaledb_functions.show_connection_cache() - WHERE user_name='alice'; - RESET ROLE; - DROP TABLE conditions; - REVOKE USAGE ON FOREIGN SERVER dn1,dn2 FROM alice; - REVOKE CREATE ON SCHEMA public FROM alice; - DROP ROLE ALICE; - SELECT node_name, user_name, invalidated - FROM _timescaledb_functions.show_connection_cache() - WHERE user_name='alice'; - -]); - -# Expected output: -# -# * First row is from the SELECT query that creates the connections -# * for alice. -# -# * Second row is the output from the connection cache after SELECT -# and prior to dropping alice. The entry has invalidated=false, so -# the entry is still valid. -# -# * There is no row for the third connection cache query since the -# * connections for alice have been purged. -is( $stdout, - q[2021-09-19 18:00:00|1|23.4 -dn1|alice|f]); - -# Test DROP OWNED BY and REASSIGN OWNED BY behavior across the setup -# Create a bunch of roles and use them to set up grant dependencies and -# object ownership -$an->safe_psql( - 'postgres', - qq[ -CREATE USER regress_dep_user0; -CREATE USER regress_dep_user1; -CREATE USER regress_dep_user2; -call distributed_exec(\$\$ CREATE USER regress_dep_user0; \$\$); -call distributed_exec(\$\$ CREATE USER regress_dep_user1; \$\$); -call distributed_exec(\$\$ CREATE USER regress_dep_user2;\$\$); -GRANT USAGE ON FOREIGN SERVER dn1,dn2 TO regress_dep_user0; -GRANT USAGE ON FOREIGN SERVER dn1,dn2 TO regress_dep_user1; -GRANT USAGE ON FOREIGN SERVER dn1,dn2 TO regress_dep_user2; -GRANT CREATE ON SCHEMA public TO regress_dep_user0; -GRANT CREATE ON SCHEMA public TO regress_dep_user1; -GRANT CREATE ON SCHEMA public TO regress_dep_user2; -SET SESSION AUTHORIZATION regress_dep_user0; -CREATE TABLE conditions1 (time bigint NOT NULL, device int, temp float); -SELECT create_distributed_hypertable('conditions1', 'time', chunk_time_interval => 10); -GRANT ALL ON conditions1 TO regress_dep_user1 WITH GRANT OPTION; -SET SESSION AUTHORIZATION regress_dep_user1; -GRANT ALL ON conditions1 TO regress_dep_user2 WITH GRANT OPTION; - ]); - -# Check the access privileges an AN and DN -my $query = - q[SELECT pg_catalog.array_to_string(c.relacl, E'\n') FROM pg_catalog.pg_class c WHERE c.relname = 'conditions1';]; - -for my $node ($an, $dn1, $dn2) -{ - $node->psql_is( - 'postgres', $query, q[regress_dep_user0=arwdDxt/regress_dep_user0 -regress_dep_user1=a*r*w*d*D*x*t*/regress_dep_user0 -regress_dep_user2=a*r*w*d*D*x*t*/regress_dep_user1], - 'Node shows correct set of access privileges'); -} - -# Execute DROP OWNED BY and check the after effects on the access privileges on the AN -$an->safe_psql('postgres', 'DROP OWNED BY regress_dep_user1'); - -for my $node ($an, $dn1, $dn2) -{ - $node->psql_is( - 'postgres', $query, - q[regress_dep_user0=arwdDxt/regress_dep_user0], - 'Node shows correct set of reduced access privileges'); -} - -# Check the ownership on AN and DN post the REASSIGN -$query = - q[SELECT pg_catalog.pg_get_userbyid(c.relowner) as owner FROM pg_catalog.pg_class c WHERE c.relname = 'conditions1';]; - -$an->safe_psql('postgres', - 'REASSIGN OWNED BY regress_dep_user0 TO regress_dep_user1;'); - -for my $node ($an, $dn1, $dn2) -{ - $node->psql_is('postgres', $query, q[regress_dep_user1], - 'Node shows changed object ownership'); -} - -done_testing(); - -1; diff --git a/tsl/test/t/008_mvcc_cagg.pl b/tsl/test/t/003_mvcc_cagg.pl similarity index 100% rename from tsl/test/t/008_mvcc_cagg.pl rename to tsl/test/t/003_mvcc_cagg.pl diff --git a/tsl/test/t/004_multinode_rdwr_1pc.pl b/tsl/test/t/004_multinode_rdwr_1pc.pl deleted file mode 100644 index 909caee50c8..00000000000 --- a/tsl/test/t/004_multinode_rdwr_1pc.pl +++ /dev/null @@ -1,177 +0,0 @@ -# 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. - -# test a multi node cluster with read only queries from access node -# primary and standby nodes -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 15; - -#Initialize all the multi-node instances - -my $an = - ($ENV{PG_VERSION_MAJOR} >= 15) - ? AccessNode->new('an') - : AccessNode->get_new_node('an'); -$an->init( - allows_streaming => 1, - auth_extra => [ '--create-role', 'repl_role' ]); -$an->start; -$an->safe_psql('postgres', 'CREATE EXTENSION timescaledb'); - -my $backup_name = 'my_backup'; - -# Take backup -$an->backup($backup_name); - -# Create streaming standby linking to access node -my $an_standby = - ($ENV{PG_VERSION_MAJOR} >= 15) - ? AccessNode->new('an_standby_1') - : AccessNode->get_new_node('an_standby_1'); -$an_standby->init_from_backup($an, $backup_name, has_streaming => 1); -$an_standby->start; - -#Initialize and set up data nodes now -my $dn1 = DataNode->create('dn1'); -my $dn2 = DataNode->create('dn2'); - -$an->add_data_node($dn1); -$an->add_data_node($dn2); - -#Create a distributed hypertable and insert a few rows -$an->safe_psql( - 'postgres', - qq[ - CREATE TABLE test(time timestamp NOT NULL, device int, temp float); - SELECT create_distributed_hypertable('test', 'time', 'device', 3); - INSERT INTO test SELECT t, (abs(timestamp_hash(t::timestamp)) % 10) + 1, 0.10 FROM generate_series('2018-03-02 1:00'::TIMESTAMPTZ, '2018-03-08 1:00', '1 hour') t; - ]); - -my $query = qq[ -CREATE OR REPLACE FUNCTION read_write_function() - RETURNS VOID - LANGUAGE plpgsql AS -\$func\$ -BEGIN - CREATE TABLE t_rd_wr( - id serial PRIMARY KEY, - customerid int, - daterecorded date, - value double precision - ); -END -\$func\$; -]; - -# Create a function which does READ WRITE activity on the datanode -$an->safe_psql('postgres', "$query; CALL distributed_exec('$query');"); - -#Allow standby to catch up with the primary -$an->wait_for_catchup($an_standby, 'replay'); - -#Check that chunks are shown appropriately from the AN standby node -$query = q[SELECT * from show_chunks('test');]; - -#Query Access Standby node -$an_standby->psql_is( - 'postgres', $query, q[_timescaledb_internal._dist_hyper_1_1_chunk -_timescaledb_internal._dist_hyper_1_2_chunk -_timescaledb_internal._dist_hyper_1_3_chunk -_timescaledb_internal._dist_hyper_1_4_chunk], - 'AN Standby shows correct set of chunks'); - -#Check that SELECT queries work ok from the AN standby node -my $result = $an_standby->safe_psql('postgres', "SELECT count(*) FROM test"); -is($result, qq(145), 'streamed content on AN standby'); - -# Check that only READ-only queries can run on AN standby node -my ($ret, $stdout, $stderr) = - $an_standby->psql('postgres', 'INSERT INTO test(time) VALUES (now())'); -is($ret, qq(3), "failed as expected"); -like( - $stderr, - qr/cannot execute INSERT in a read-only transaction/, - "read only message as expected"); - -# Check that queries which connect to datanodes also remain read only -($ret, $stdout, $stderr) = - $an_standby->psql('postgres', - 'CALL distributed_exec($$ CREATE USER testrole WITH LOGIN $$)'); -is($ret, qq(3), "failed as expected"); -like( - $stderr, - qr/cannot execute CREATE ROLE in a read-only transaction/, - "read only message for DNs as expected"); - -# Check that function doing read write activity doesn't work -($ret, $stdout, $stderr) = - $an_standby->psql('postgres', - 'CALL distributed_exec($$ SELECT read_write_function() $$)'); -is($ret, qq(3), "failed as expected"); -like( - $stderr, - qr/cannot execute CREATE TABLE in a read-only transaction/, - "read only message for DNs as expected"); - -$an->append_conf( - 'postgresql.conf', qq[ - client_min_messages = 'debug3' - ]); -$an->restart; -# Check that AN primary uses 2PC for read write transactions when multiple DNs -# are involved -($ret, $stdout, $stderr) = - $an->psql('postgres', - 'BEGIN TRANSACTION READ WRITE; SELECT count(*) FROM TEST; ROLLBACK;'); -like( - $stderr, - qr/use 2PC: true/, - "read write transaction uses 2PC with 2DNs on AN as expected"); - -# Check that AN primary uses 2PC for read write transactions even when SINGLE DN -# is involved -($ret, $stdout, $stderr) = $an->psql('postgres', - 'CALL distributed_exec($$ CREATE USER testrole WITH LOGIN $$, node_list => \'{ "dn1" }\'); ROLLBACK;' -); -like( - $stderr, - qr/use 2PC: true/, - "read write transaction uses 2PC even with ONE DN from AN as expected"); - -# Check that AN primary uses 1PC for READ ONLY SERIALIZABLE transactions even when -# multiple DNs are involved -($ret, $stdout, $stderr) = $an->psql('postgres', - 'BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY; SELECT count(*) FROM TEST; ROLLBACK;' -); -like( - $stderr, - qr/use 2PC: false/, - "read only serializable transaction uses 1PC on AN as expected"); - -# Check that AN primary uses 1PC for READ ONLY transactions even when multiple DNs -# are involved -($ret, $stdout, $stderr) = - $an->psql('postgres', - 'BEGIN TRANSACTION READ ONLY; SELECT count(*) FROM TEST; ROLLBACK;'); -like( - $stderr, - qr/use 2PC: false/, - "read only transaction uses 1PC on AN as expected"); - -# Check that standby can do READ WRITE queries post promotion -$an_standby->promote; -$an_standby->safe_psql('postgres', 'INSERT INTO test(time) VALUES (now())'); -$result = $an_standby->safe_psql('postgres', "SELECT count(*) FROM test"); -is($result, qq(146), 'READ WRITE content on AN standby'); - -# Read write function should also work now -$an_standby->safe_psql('postgres', - 'CALL distributed_exec($$ SELECT read_write_function() $$)'); - -done_testing(); - -1; diff --git a/tsl/test/t/005_add_data_node.pl b/tsl/test/t/005_add_data_node.pl deleted file mode 100644 index ecd4ef44367..00000000000 --- a/tsl/test/t/005_add_data_node.pl +++ /dev/null @@ -1,39 +0,0 @@ -# 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. - -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 1; - -# -# Make sure AN does not crash and produce correct error in case if the -# DN is not properly configured. -# -# Issue: -# https://github.com/timescale/timescaledb/issues/3951 - -my $an = AccessNode->create('an'); -my $dn = - ($ENV{PG_VERSION_MAJOR} >= 15) - ? PostgreSQL::Test::Cluster->new('dn') - : PostgresNode->get_new_node('dn'); -$dn->init(); -$dn->start(); - -my $name = $dn->name; -my $host = $dn->host; -my $port = $dn->port; -my ($ret, $stdout, $stderr) = - $an->psql('postgres', - "SELECT add_data_node('$name', host => '$host', port => $port)"); -like( - $stderr, - qr/extension "timescaledb" must be preloaded/, - 'failure when adding data node'); - -done_testing(); - -1; diff --git a/tsl/test/t/007_healthcheck.pl b/tsl/test/t/007_healthcheck.pl deleted file mode 100644 index 4d0fe3fef0d..00000000000 --- a/tsl/test/t/007_healthcheck.pl +++ /dev/null @@ -1,41 +0,0 @@ -# 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. - -use strict; -use warnings; -use AccessNode; -use DataNode; -use Test::More tests => 4; - -#Initialize all the multi-node instances -my $an = AccessNode->create('an'); -my $dn1 = DataNode->create('dn1'); -my $dn2 = DataNode->create('dn2'); - -$an->add_data_node($dn1); -$an->add_data_node($dn2); - -$an->psql_is( - 'postgres', - 'SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST', - q[|t|f| -dn1|t|f| -dn2|t|f|], 'Health check shows healthy AN and two healthy DNs'); - -# Stop a data node to simulate failure -$dn1->stop('fast'); - -# Health check will currently fail with an error when a data node -# cannot be contacted. This should be fixed so that the health check -# instead returns a negative status for the node. -my ($ret, $stdout, $stderr) = $an->psql('postgres', - 'SELECT * FROM _timescaledb_functions.health() ORDER BY 1 NULLS FIRST;'); - -# psql return error code 3 in case of failure in script -is($ret, qq(3), "expect error code 3 due to failed data node"); - -done_testing(); - -1; - diff --git a/tsl/test/t/CMakeLists.txt b/tsl/test/t/CMakeLists.txt index 2131ff223b0..d8c4eab15f4 100644 --- a/tsl/test/t/CMakeLists.txt +++ b/tsl/test/t/CMakeLists.txt @@ -1,21 +1,6 @@ -set(PROVE_TEST_FILES 009_logrepl_decomp_marker.pl) +set(PROVE_TEST_FILES 001_job_crash_log.pl 002_logrepl_decomp_marker.pl) -set(PROVE_DEBUG_TEST_FILES 008_mvcc_cagg.pl) - -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list(APPEND PROVE_TEST_FILES 001_simple_multinode.pl 003_connections_privs.pl) -endif() - -if(ENABLE_MULTINODE_TESTS AND ${PG_VERSION_MAJOR} LESS "16") - list( - APPEND - PROVE_DEBUG_TEST_FILES - 002_chunk_copy_move.pl - 004_multinode_rdwr_1pc.pl - 005_add_data_node.pl - 006_job_crash_log.pl - 007_healthcheck.pl) -endif() +set(PROVE_DEBUG_TEST_FILES 003_mvcc_cagg.pl) if(CMAKE_BUILD_TYPE MATCHES Debug) list(APPEND PROVE_TEST_FILES ${PROVE_DEBUG_TEST_FILES})