From 04d614e32ecf24339110da1eb8ea3c7512be3d54 Mon Sep 17 00:00:00 2001 From: Sven Klemm Date: Mon, 18 Jan 2021 09:02:02 +0100 Subject: [PATCH] Run regresscheck on PG13 --- .github/workflows/linux-build-and-test.yaml | 1 + test/expected/agg_bookends-13.out | 1164 ++++++++ test/expected/append-13.out | 2252 ++++++++++++++ test/expected/chunk_adaptive-13.out | 766 +++++ test/expected/custom_type-13.out | 100 + test/expected/insert-13.out | 661 +++++ test/expected/multi_transaction_index-13.out | 404 +++ test/expected/parallel-13.out | 445 +++ test/expected/partition-13.out | 521 ++++ test/expected/plan_expand_hypertable-13.out | 2735 ++++++++++++++++++ test/expected/plan_hashagg-13.out | 329 +++ test/expected/query-13.out | 408 +++ test/expected/sort_optimization-13.out | 73 + test/expected/sql_query-13.out | 279 ++ test/sql/include/join_query.sql | 1 + 15 files changed, 10139 insertions(+) create mode 100644 test/expected/agg_bookends-13.out create mode 100644 test/expected/append-13.out create mode 100644 test/expected/chunk_adaptive-13.out create mode 100644 test/expected/custom_type-13.out create mode 100644 test/expected/insert-13.out create mode 100644 test/expected/multi_transaction_index-13.out create mode 100644 test/expected/parallel-13.out create mode 100644 test/expected/partition-13.out create mode 100644 test/expected/plan_expand_hypertable-13.out create mode 100644 test/expected/plan_hashagg-13.out create mode 100644 test/expected/query-13.out create mode 100644 test/expected/sort_optimization-13.out create mode 100644 test/expected/sql_query-13.out diff --git a/.github/workflows/linux-build-and-test.yaml b/.github/workflows/linux-build-and-test.yaml index 92c9e197f..c3637ac97 100644 --- a/.github/workflows/linux-build-and-test.yaml +++ b/.github/workflows/linux-build-and-test.yaml @@ -105,6 +105,7 @@ jobs: set -o pipefail if [[ "${{ matrix.pg }}" == "13.1" ]]; then make -k -C build isolationcheck isolationcheck-t ${{ matrix.installcheck_args }} | tee installcheck.log + make -k -C build regresscheck | tee -a installcheck.log else make -k -C build installcheck ${{ matrix.installcheck_args }} | tee installcheck.log fi diff --git a/test/expected/agg_bookends-13.out b/test/expected/agg_bookends-13.out new file mode 100644 index 000000000..841c86949 --- /dev/null +++ b/test/expected/agg_bookends-13.out @@ -0,0 +1,1164 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set TEST_BASE_NAME agg_bookends +SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') as "TEST_LOAD_NAME", + format('include/%s_query.sql', :'TEST_BASE_NAME') as "TEST_QUERY_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized result" --label "Optimized result" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset +\set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' +\ir :TEST_LOAD_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE btest(time timestamp NOT NULL, time_alt timestamp, gp INTEGER, temp float, strid TEXT DEFAULT 'testing'); +SELECT schema_name, table_name, created FROM create_hypertable('btest', 'time'); + schema_name | table_name | created +-------------+------------+--------- + public | btest | t +(1 row) + +INSERT INTO btest VALUES('2017-01-20T09:00:01', '2017-01-20T10:00:00', 1, 22.5); +INSERT INTO btest VALUES('2017-01-20T09:00:21', '2017-01-20T09:00:59', 1, 21.2); +INSERT INTO btest VALUES('2017-01-20T09:00:47', '2017-01-20T09:00:58', 1, 25.1); +INSERT INTO btest VALUES('2017-01-20T09:00:02', '2017-01-20T09:00:57', 2, 35.5); +INSERT INTO btest VALUES('2017-01-20T09:00:21', '2017-01-20T09:00:56', 2, 30.2); +--TOASTED; +INSERT INTO btest VALUES('2017-01-20T09:00:43', '2017-01-20T09:01:55', 2, 20.1, repeat('xyz', 1000000) ); +CREATE TABLE btest_numeric (time timestamp NOT NULL, quantity numeric); +SELECT schema_name, table_name, created FROM create_hypertable('btest_numeric', 'time'); + schema_name | table_name | created +-------------+---------------+--------- + public | btest_numeric | t +(1 row) + +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- canary for results diff +-- this should be only output of results diff +SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.enable_optimizations')) v(setting); + setting | value +----------------------------------+------- + timescaledb.enable_optimizations | on +(1 row) + +:PREFIX SELECT time, gp, temp FROM btest ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on btest (actual rows=6 loops=1) + Order: btest."time" + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=6 loops=1) +(3 rows) + +:PREFIX SELECT last(temp, time) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) +(7 rows) + +:PREFIX SELECT first(temp, time) FROM btest; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) +(7 rows) + +:PREFIX SELECT last(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(2 rows) + +:PREFIX SELECT first(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(2 rows) + +:PREFIX SELECT gp, last(temp, time) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(7 rows) + +:PREFIX SELECT gp, first(temp, time) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(7 rows) + +--check whole row +:PREFIX SELECT gp, first(btest, time) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(7 rows) + +--check toasted col +:PREFIX SELECT gp, left(last(strid, time), 10) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(7 rows) + +:PREFIX SELECT gp, last(temp, strid) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) +(7 rows) + +BEGIN; +--check null value as last element +INSERT INTO btest VALUES('2018-01-20T09:00:43', '2017-01-20T09:00:55', 2, NULL); +:PREFIX SELECT last(temp, time) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(9 rows) + +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest VALUES('2019-01-20T09:00:43', '2018-01-20T09:00:55', 2, 30.5); +:PREFIX SELECT last(temp, time) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(11 rows) + +--check null cmp element is skipped +INSERT INTO btest VALUES('2018-01-20T09:00:43', NULL, 2, 32.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=9 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) +(5 rows) + +-- fist returns NULL value +:PREFIX SELECT first(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=9 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) +(5 rows) + +-- test first return non NULL value +INSERT INTO btest VALUES('2016-01-20T09:00:00', '2016-01-20T09:00:00', 2, 36.5); +:PREFIX SELECT first(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=10 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) +(6 rows) + +--check non null cmp element insert after null cmp +INSERT INTO btest VALUES('2020-01-20T09:00:43', '2020-01-20T09:00:43', 2, 35.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(7 rows) + +:PREFIX SELECT first(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(7 rows) + +--cmp nulls should be ignored and not present in groups +:PREFIX SELECT gp, last(temp, time_alt) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(12 rows) + +--Previously, some bugs were found with NULLS and numeric types, so test that +INSERT INTO btest_numeric VALUES ('2019-01-20T09:00:43', NULL); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest_numeric (actual rows=1 loops=1) + Order: btest_numeric."time" DESC + -> Index Scan using _hyper_2_6_chunk_btest_numeric_time_idx on _hyper_2_6_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) +(7 rows) + +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest_numeric (actual rows=1 loops=1) + Order: btest_numeric."time" DESC + -> Index Scan using _hyper_2_7_chunk_btest_numeric_time_idx on _hyper_2_7_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_2_6_chunk_btest_numeric_time_idx on _hyper_2_6_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(9 rows) + +-- do index scan for last +:PREFIX SELECT last(temp, time) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(15 rows) + +-- do index scan for first +:PREFIX SELECT first(temp, time) FROM btest; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" + -> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(15 rows) + +-- can't do index scan when ordering on non-index column +:PREFIX SELECT first(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(7 rows) + +-- do index scan for subquery +:PREFIX SELECT * FROM (SELECT last(temp, time) FROM btest) last; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(15 rows) + +-- can't do index scan when using group by +:PREFIX SELECT last(temp, time) FROM btest GROUP BY gp ORDER BY gp; + QUERY PLAN +------------------------------------------------------------------------ + Sort (actual rows=2 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> HashAggregate (actual rows=2 loops=1) + Group Key: _hyper_1_1_chunk.gp + Batches: 1 + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(12 rows) + +-- do index scan when agg function is used in CTE subquery +:PREFIX WITH last_temp AS (SELECT last(temp, time) FROM btest) SELECT * from last_temp; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(15 rows) + +-- do index scan when using both FIRST and LAST aggregate functions +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $1) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + InitPlan 2 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest btest_1 (actual rows=1 loops=1) + Order: btest_1."time" + -> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk _hyper_1_4_chunk_1 (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk _hyper_1_3_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk _hyper_1_5_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) +(29 rows) + +-- verify results when using both FIRST and LAST +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $1) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + InitPlan 2 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest btest_1 (actual rows=1 loops=1) + Order: btest_1."time" + -> Index Scan Backward using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk _hyper_1_4_chunk_1 (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk _hyper_1_1_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk _hyper_1_2_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk _hyper_1_3_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk _hyper_1_5_chunk_1 (never executed) + Index Cond: ("time" IS NOT NULL) +(29 rows) + +-- do index scan when using WHERE +:PREFIX SELECT last(temp, time) FROM btest WHERE time <= '2017-01-20T09:00:02'; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: (("time" IS NOT NULL) AND ("time" <= 'Fri Jan 20 09:00:02 2017'::timestamp without time zone)) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: (("time" IS NOT NULL) AND ("time" <= 'Fri Jan 20 09:00:02 2017'::timestamp without time zone)) +(9 rows) + +-- can't do index scan for MAX and LAST combined (MinMax optimization fails when having different aggregate functions) +:PREFIX SELECT max(time), last(temp, time) FROM btest; + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(7 rows) + +-- can't do index scan when using FIRST/LAST in ORDER BY +:PREFIX SELECT last(temp, time) FROM btest ORDER BY last(temp, time); + QUERY PLAN +------------------------------------------------------------------------ + Sort (actual rows=1 loops=1) + Sort Key: (last(_hyper_1_1_chunk.temp, _hyper_1_1_chunk."time")) + Sort Method: quicksort + -> Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(10 rows) + +-- do index scan +:PREFIX SELECT last(temp, time) FROM btest WHERE temp < 30; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=0 loops=1) + Index Cond: ("time" IS NOT NULL) + Filter: (temp < '30'::double precision) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (actual rows=0 loops=1) + Index Cond: ("time" IS NOT NULL) + Filter: (temp < '30'::double precision) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (actual rows=0 loops=1) + Index Cond: ("time" IS NOT NULL) + Filter: (temp < '30'::double precision) + Rows Removed by Filter: 2 + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + Filter: (temp < '30'::double precision) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + Filter: (temp < '30'::double precision) +(23 rows) + +-- SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- do index scan +:PREFIX SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)) + -> Index Scan Backward using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)) + -> Index Scan Backward using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)) + -> Index Scan Backward using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (never executed) + Index Cond: (("time" IS NOT NULL) AND ("time" >= 'Fri Jan 20 09:00:47 2017'::timestamp without time zone)) +(13 rows) + +-- can't do index scan when using WINDOW function +:PREFIX SELECT gp, last(temp, time) OVER (PARTITION BY gp) AS last FROM btest; + QUERY PLAN +------------------------------------------------------------------------ + WindowAgg (actual rows=11 loops=1) + -> Sort (actual rows=11 loops=1) + Sort Key: _hyper_1_1_chunk.gp + Sort Method: quicksort + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(10 rows) + +-- test constants +:PREFIX SELECT first(100, 100) FROM btest; + QUERY PLAN +-------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Result (actual rows=1 loops=1) + -> Append (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_2_chunk (never executed) + -> Seq Scan on _hyper_1_3_chunk (never executed) + -> Seq Scan on _hyper_1_4_chunk (never executed) + -> Seq Scan on _hyper_1_5_chunk (never executed) +(10 rows) + +-- create an index so we can test optimization +CREATE INDEX btest_time_alt_idx ON btest(time_alt); +:PREFIX SELECT last(temp, time_alt) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Merge Append (actual rows=1 loops=1) + Sort Key: _hyper_1_1_chunk.time_alt DESC + -> Index Scan Backward using _hyper_1_1_chunk_btest_time_alt_idx on _hyper_1_1_chunk (actual rows=1 loops=1) + Index Cond: (time_alt IS NOT NULL) + -> Index Scan Backward using _hyper_1_2_chunk_btest_time_alt_idx on _hyper_1_2_chunk (actual rows=1 loops=1) + Index Cond: (time_alt IS NOT NULL) + -> Index Scan Backward using _hyper_1_3_chunk_btest_time_alt_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: (time_alt IS NOT NULL) + -> Index Scan Backward using _hyper_1_4_chunk_btest_time_alt_idx on _hyper_1_4_chunk (actual rows=1 loops=1) + Index Cond: (time_alt IS NOT NULL) + -> Index Scan Backward using _hyper_1_5_chunk_btest_time_alt_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: (time_alt IS NOT NULL) +(15 rows) + +--test nested FIRST/LAST - should optimize +:PREFIX SELECT abs(last(temp, time)) FROM btest; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on btest (actual rows=1 loops=1) + Order: btest."time" DESC + -> Index Scan using _hyper_1_5_chunk_btest_time_idx on _hyper_1_5_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_3_chunk_btest_time_idx on _hyper_1_3_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_2_chunk_btest_time_idx on _hyper_1_2_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_1_chunk_btest_time_idx on _hyper_1_1_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + -> Index Scan using _hyper_1_4_chunk_btest_time_idx on _hyper_1_4_chunk (never executed) + Index Cond: ("time" IS NOT NULL) +(15 rows) + +-- test nested FIRST/LAST in ORDER BY - no optimization possible +:PREFIX SELECT abs(last(temp, time)) FROM btest ORDER BY abs(last(temp,time)); + QUERY PLAN +------------------------------------------------------------------------- + Sort (actual rows=1 loops=1) + Sort Key: (abs(last(_hyper_1_1_chunk.temp, _hyper_1_1_chunk."time"))) + Sort Method: quicksort + -> Aggregate (actual rows=1 loops=1) + -> Append (actual rows=11 loops=1) + -> Seq Scan on _hyper_1_1_chunk (actual rows=6 loops=1) + -> Seq Scan on _hyper_1_2_chunk (actual rows=2 loops=1) + -> Seq Scan on _hyper_1_3_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_4_chunk (actual rows=1 loops=1) + -> Seq Scan on _hyper_1_5_chunk (actual rows=1 loops=1) +(10 rows) + +ROLLBACK; +-- we want test results as part of the output too to make sure we produce correct output +\set PREFIX '' +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- canary for results diff +-- this should be only output of results diff +SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.enable_optimizations')) v(setting); + setting | value +----------------------------------+------- + timescaledb.enable_optimizations | on +(1 row) + +:PREFIX SELECT time, gp, temp FROM btest ORDER BY time; + time | gp | temp +--------------------------+----+------ + Fri Jan 20 09:00:01 2017 | 1 | 22.5 + Fri Jan 20 09:00:02 2017 | 2 | 35.5 + Fri Jan 20 09:00:21 2017 | 1 | 21.2 + Fri Jan 20 09:00:21 2017 | 2 | 30.2 + Fri Jan 20 09:00:43 2017 | 2 | 20.1 + Fri Jan 20 09:00:47 2017 | 1 | 25.1 +(6 rows) + +:PREFIX SELECT last(temp, time) FROM btest; + last +------ + 25.1 +(1 row) + +:PREFIX SELECT first(temp, time) FROM btest; + first +------- + 22.5 +(1 row) + +:PREFIX SELECT last(temp, time_alt) FROM btest; + last +------ + 22.5 +(1 row) + +:PREFIX SELECT first(temp, time_alt) FROM btest; + first +------- + 30.2 +(1 row) + +:PREFIX SELECT gp, last(temp, time) FROM btest GROUP BY gp ORDER BY gp; + gp | last +----+------ + 1 | 25.1 + 2 | 20.1 +(2 rows) + +:PREFIX SELECT gp, first(temp, time) FROM btest GROUP BY gp ORDER BY gp; + gp | first +----+------- + 1 | 22.5 + 2 | 35.5 +(2 rows) + +--check whole row +:PREFIX SELECT gp, first(btest, time) FROM btest GROUP BY gp ORDER BY gp; + gp | first +----+------------------------------------------------------------------------ + 1 | ("Fri Jan 20 09:00:01 2017","Fri Jan 20 10:00:00 2017",1,22.5,testing) + 2 | ("Fri Jan 20 09:00:02 2017","Fri Jan 20 09:00:57 2017",2,35.5,testing) +(2 rows) + +--check toasted col +:PREFIX SELECT gp, left(last(strid, time), 10) FROM btest GROUP BY gp ORDER BY gp; + gp | left +----+------------ + 1 | testing + 2 | xyzxyzxyzx +(2 rows) + +:PREFIX SELECT gp, last(temp, strid) FROM btest GROUP BY gp ORDER BY gp; + gp | last +----+------ + 1 | 22.5 + 2 | 20.1 +(2 rows) + +BEGIN; +--check null value as last element +INSERT INTO btest VALUES('2018-01-20T09:00:43', '2017-01-20T09:00:55', 2, NULL); +:PREFIX SELECT last(temp, time) FROM btest; + last +------ + +(1 row) + +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest VALUES('2019-01-20T09:00:43', '2018-01-20T09:00:55', 2, 30.5); +:PREFIX SELECT last(temp, time) FROM btest; + last +------ + 30.5 +(1 row) + +--check null cmp element is skipped +INSERT INTO btest VALUES('2018-01-20T09:00:43', NULL, 2, 32.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; + last +------ + 30.5 +(1 row) + +-- fist returns NULL value +:PREFIX SELECT first(temp, time_alt) FROM btest; + first +------- + +(1 row) + +-- test first return non NULL value +INSERT INTO btest VALUES('2016-01-20T09:00:00', '2016-01-20T09:00:00', 2, 36.5); +:PREFIX SELECT first(temp, time_alt) FROM btest; + first +------- + 36.5 +(1 row) + +--check non null cmp element insert after null cmp +INSERT INTO btest VALUES('2020-01-20T09:00:43', '2020-01-20T09:00:43', 2, 35.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; + last +------ + 35.3 +(1 row) + +:PREFIX SELECT first(temp, time_alt) FROM btest; + first +------- + 36.5 +(1 row) + +--cmp nulls should be ignored and not present in groups +:PREFIX SELECT gp, last(temp, time_alt) FROM btest GROUP BY gp ORDER BY gp; + gp | last +----+------ + 1 | 22.5 + 2 | 35.3 +(2 rows) + +--Previously, some bugs were found with NULLS and numeric types, so test that +INSERT INTO btest_numeric VALUES ('2019-01-20T09:00:43', NULL); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; + last +------ + +(1 row) + +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; + last +------ + 30.5 +(1 row) + +-- do index scan for last +:PREFIX SELECT last(temp, time) FROM btest; + last +------ + 35.3 +(1 row) + +-- do index scan for first +:PREFIX SELECT first(temp, time) FROM btest; + first +------- + 36.5 +(1 row) + +-- can't do index scan when ordering on non-index column +:PREFIX SELECT first(temp, time_alt) FROM btest; + first +------- + 36.5 +(1 row) + +-- do index scan for subquery +:PREFIX SELECT * FROM (SELECT last(temp, time) FROM btest) last; + last +------ + 35.3 +(1 row) + +-- can't do index scan when using group by +:PREFIX SELECT last(temp, time) FROM btest GROUP BY gp ORDER BY gp; + last +------ + 25.1 + 35.3 +(2 rows) + +-- do index scan when agg function is used in CTE subquery +:PREFIX WITH last_temp AS (SELECT last(temp, time) FROM btest) SELECT * from last_temp; + last +------ + 35.3 +(1 row) + +-- do index scan when using both FIRST and LAST aggregate functions +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; + first | last +-------+------ + 36.5 | 35.3 +(1 row) + +-- verify results when using both FIRST and LAST +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; + first | last +-------+------ + 36.5 | 35.3 +(1 row) + +-- do index scan when using WHERE +:PREFIX SELECT last(temp, time) FROM btest WHERE time <= '2017-01-20T09:00:02'; + last +------ + 35.5 +(1 row) + +-- can't do index scan for MAX and LAST combined (MinMax optimization fails when having different aggregate functions) +:PREFIX SELECT max(time), last(temp, time) FROM btest; + max | last +--------------------------+------ + Mon Jan 20 09:00:43 2020 | 35.3 +(1 row) + +-- can't do index scan when using FIRST/LAST in ORDER BY +:PREFIX SELECT last(temp, time) FROM btest ORDER BY last(temp, time); + last +------ + 35.3 +(1 row) + +-- do index scan +:PREFIX SELECT last(temp, time) FROM btest WHERE temp < 30; + last +------ + 25.1 +(1 row) + +-- SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- do index scan +:PREFIX SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; + first +------- + 25.1 +(1 row) + +-- can't do index scan when using WINDOW function +:PREFIX SELECT gp, last(temp, time) OVER (PARTITION BY gp) AS last FROM btest; + gp | last +----+------ + 1 | 25.1 + 1 | 25.1 + 1 | 25.1 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 + 2 | 35.3 +(11 rows) + +-- test constants +:PREFIX SELECT first(100, 100) FROM btest; + first +------- + 100 +(1 row) + +-- create an index so we can test optimization +CREATE INDEX btest_time_alt_idx ON btest(time_alt); +:PREFIX SELECT last(temp, time_alt) FROM btest; + last +------ + 35.3 +(1 row) + +--test nested FIRST/LAST - should optimize +:PREFIX SELECT abs(last(temp, time)) FROM btest; + abs +------ + 35.3 +(1 row) + +-- test nested FIRST/LAST in ORDER BY - no optimization possible +:PREFIX SELECT abs(last(temp, time)) FROM btest ORDER BY abs(last(temp,time)); + abs +------ + 35.3 +(1 row) + +ROLLBACK; +-- diff results with optimizations disabled and enabled +\o :TEST_RESULTS_UNOPTIMIZED +SET timescaledb.enable_optimizations TO false; +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- canary for results diff +-- this should be only output of results diff +SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.enable_optimizations')) v(setting); +:PREFIX SELECT time, gp, temp FROM btest ORDER BY time; +:PREFIX SELECT last(temp, time) FROM btest; +:PREFIX SELECT first(temp, time) FROM btest; +:PREFIX SELECT last(temp, time_alt) FROM btest; +:PREFIX SELECT first(temp, time_alt) FROM btest; +:PREFIX SELECT gp, last(temp, time) FROM btest GROUP BY gp ORDER BY gp; +:PREFIX SELECT gp, first(temp, time) FROM btest GROUP BY gp ORDER BY gp; +--check whole row +:PREFIX SELECT gp, first(btest, time) FROM btest GROUP BY gp ORDER BY gp; +--check toasted col +:PREFIX SELECT gp, left(last(strid, time), 10) FROM btest GROUP BY gp ORDER BY gp; +:PREFIX SELECT gp, last(temp, strid) FROM btest GROUP BY gp ORDER BY gp; +BEGIN; +--check null value as last element +INSERT INTO btest VALUES('2018-01-20T09:00:43', '2017-01-20T09:00:55', 2, NULL); +:PREFIX SELECT last(temp, time) FROM btest; +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest VALUES('2019-01-20T09:00:43', '2018-01-20T09:00:55', 2, 30.5); +:PREFIX SELECT last(temp, time) FROM btest; +--check null cmp element is skipped +INSERT INTO btest VALUES('2018-01-20T09:00:43', NULL, 2, 32.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; +-- fist returns NULL value +:PREFIX SELECT first(temp, time_alt) FROM btest; +-- test first return non NULL value +INSERT INTO btest VALUES('2016-01-20T09:00:00', '2016-01-20T09:00:00', 2, 36.5); +:PREFIX SELECT first(temp, time_alt) FROM btest; +--check non null cmp element insert after null cmp +INSERT INTO btest VALUES('2020-01-20T09:00:43', '2020-01-20T09:00:43', 2, 35.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; +:PREFIX SELECT first(temp, time_alt) FROM btest; +--cmp nulls should be ignored and not present in groups +:PREFIX SELECT gp, last(temp, time_alt) FROM btest GROUP BY gp ORDER BY gp; +--Previously, some bugs were found with NULLS and numeric types, so test that +INSERT INTO btest_numeric VALUES ('2019-01-20T09:00:43', NULL); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; +-- do index scan for last +:PREFIX SELECT last(temp, time) FROM btest; +-- do index scan for first +:PREFIX SELECT first(temp, time) FROM btest; +-- can't do index scan when ordering on non-index column +:PREFIX SELECT first(temp, time_alt) FROM btest; +-- do index scan for subquery +:PREFIX SELECT * FROM (SELECT last(temp, time) FROM btest) last; +-- can't do index scan when using group by +:PREFIX SELECT last(temp, time) FROM btest GROUP BY gp ORDER BY gp; +-- do index scan when agg function is used in CTE subquery +:PREFIX WITH last_temp AS (SELECT last(temp, time) FROM btest) SELECT * from last_temp; +-- do index scan when using both FIRST and LAST aggregate functions +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; +-- verify results when using both FIRST and LAST +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; +-- do index scan when using WHERE +:PREFIX SELECT last(temp, time) FROM btest WHERE time <= '2017-01-20T09:00:02'; +-- can't do index scan for MAX and LAST combined (MinMax optimization fails when having different aggregate functions) +:PREFIX SELECT max(time), last(temp, time) FROM btest; +-- can't do index scan when using FIRST/LAST in ORDER BY +:PREFIX SELECT last(temp, time) FROM btest ORDER BY last(temp, time); +-- do index scan +:PREFIX SELECT last(temp, time) FROM btest WHERE temp < 30; +-- SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- do index scan +:PREFIX SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- can't do index scan when using WINDOW function +:PREFIX SELECT gp, last(temp, time) OVER (PARTITION BY gp) AS last FROM btest; +-- test constants +:PREFIX SELECT first(100, 100) FROM btest; +-- create an index so we can test optimization +CREATE INDEX btest_time_alt_idx ON btest(time_alt); +:PREFIX SELECT last(temp, time_alt) FROM btest; +--test nested FIRST/LAST - should optimize +:PREFIX SELECT abs(last(temp, time)) FROM btest; +-- test nested FIRST/LAST in ORDER BY - no optimization possible +:PREFIX SELECT abs(last(temp, time)) FROM btest ORDER BY abs(last(temp,time)); +ROLLBACK; +\o +\o :TEST_RESULTS_OPTIMIZED +SET timescaledb.enable_optimizations TO true; +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- canary for results diff +-- this should be only output of results diff +SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.enable_optimizations')) v(setting); +:PREFIX SELECT time, gp, temp FROM btest ORDER BY time; +:PREFIX SELECT last(temp, time) FROM btest; +:PREFIX SELECT first(temp, time) FROM btest; +:PREFIX SELECT last(temp, time_alt) FROM btest; +:PREFIX SELECT first(temp, time_alt) FROM btest; +:PREFIX SELECT gp, last(temp, time) FROM btest GROUP BY gp ORDER BY gp; +:PREFIX SELECT gp, first(temp, time) FROM btest GROUP BY gp ORDER BY gp; +--check whole row +:PREFIX SELECT gp, first(btest, time) FROM btest GROUP BY gp ORDER BY gp; +--check toasted col +:PREFIX SELECT gp, left(last(strid, time), 10) FROM btest GROUP BY gp ORDER BY gp; +:PREFIX SELECT gp, last(temp, strid) FROM btest GROUP BY gp ORDER BY gp; +BEGIN; +--check null value as last element +INSERT INTO btest VALUES('2018-01-20T09:00:43', '2017-01-20T09:00:55', 2, NULL); +:PREFIX SELECT last(temp, time) FROM btest; +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest VALUES('2019-01-20T09:00:43', '2018-01-20T09:00:55', 2, 30.5); +:PREFIX SELECT last(temp, time) FROM btest; +--check null cmp element is skipped +INSERT INTO btest VALUES('2018-01-20T09:00:43', NULL, 2, 32.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; +-- fist returns NULL value +:PREFIX SELECT first(temp, time_alt) FROM btest; +-- test first return non NULL value +INSERT INTO btest VALUES('2016-01-20T09:00:00', '2016-01-20T09:00:00', 2, 36.5); +:PREFIX SELECT first(temp, time_alt) FROM btest; +--check non null cmp element insert after null cmp +INSERT INTO btest VALUES('2020-01-20T09:00:43', '2020-01-20T09:00:43', 2, 35.3); +:PREFIX SELECT last(temp, time_alt) FROM btest; +:PREFIX SELECT first(temp, time_alt) FROM btest; +--cmp nulls should be ignored and not present in groups +:PREFIX SELECT gp, last(temp, time_alt) FROM btest GROUP BY gp ORDER BY gp; +--Previously, some bugs were found with NULLS and numeric types, so test that +INSERT INTO btest_numeric VALUES ('2019-01-20T09:00:43', NULL); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; +--check non-null element "overrides" NULL because it comes after. +INSERT INTO btest_numeric VALUES('2020-01-20T09:00:43', 30.5); +:PREFIX SELECT last(quantity, time) FROM btest_numeric; +-- do index scan for last +:PREFIX SELECT last(temp, time) FROM btest; +-- do index scan for first +:PREFIX SELECT first(temp, time) FROM btest; +-- can't do index scan when ordering on non-index column +:PREFIX SELECT first(temp, time_alt) FROM btest; +-- do index scan for subquery +:PREFIX SELECT * FROM (SELECT last(temp, time) FROM btest) last; +-- can't do index scan when using group by +:PREFIX SELECT last(temp, time) FROM btest GROUP BY gp ORDER BY gp; +-- do index scan when agg function is used in CTE subquery +:PREFIX WITH last_temp AS (SELECT last(temp, time) FROM btest) SELECT * from last_temp; +-- do index scan when using both FIRST and LAST aggregate functions +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; +-- verify results when using both FIRST and LAST +:PREFIX SELECT first(temp, time), last(temp, time) FROM btest; +-- do index scan when using WHERE +:PREFIX SELECT last(temp, time) FROM btest WHERE time <= '2017-01-20T09:00:02'; +-- can't do index scan for MAX and LAST combined (MinMax optimization fails when having different aggregate functions) +:PREFIX SELECT max(time), last(temp, time) FROM btest; +-- can't do index scan when using FIRST/LAST in ORDER BY +:PREFIX SELECT last(temp, time) FROM btest ORDER BY last(temp, time); +-- do index scan +:PREFIX SELECT last(temp, time) FROM btest WHERE temp < 30; +-- SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- do index scan +:PREFIX SELECT first(temp, time) FROM btest WHERE time >= '2017-01-20 09:00:47'; +-- can't do index scan when using WINDOW function +:PREFIX SELECT gp, last(temp, time) OVER (PARTITION BY gp) AS last FROM btest; +-- test constants +:PREFIX SELECT first(100, 100) FROM btest; +-- create an index so we can test optimization +CREATE INDEX btest_time_alt_idx ON btest(time_alt); +:PREFIX SELECT last(temp, time_alt) FROM btest; +--test nested FIRST/LAST - should optimize +:PREFIX SELECT abs(last(temp, time)) FROM btest; +-- test nested FIRST/LAST in ORDER BY - no optimization possible +:PREFIX SELECT abs(last(temp, time)) FROM btest ORDER BY abs(last(temp,time)); +ROLLBACK; +\o +:DIFF_CMD +--- Unoptimized result ++++ Optimized result +@@ -1,6 +1,6 @@ + setting | value + ----------------------------------+------- +- timescaledb.enable_optimizations | off ++ timescaledb.enable_optimizations | on + (1 row) + + time | gp | temp diff --git a/test/expected/append-13.out b/test/expected/append-13.out new file mode 100644 index 000000000..93c8269c3 --- /dev/null +++ b/test/expected/append-13.out @@ -0,0 +1,2252 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set TEST_BASE_NAME append +SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') as "TEST_LOAD_NAME", + format('include/%s_query.sql', :'TEST_BASE_NAME') as "TEST_QUERY_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized results" --label "Optimized results" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset +\set PREFIX 'EXPLAIN (analyze, costs off, timing off, summary off)' +\ir :TEST_LOAD_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- create a now() function for repeatable testing that always returns +-- the same timestamp. It needs to be marked STABLE +CREATE OR REPLACE FUNCTION now_s() +RETURNS timestamptz LANGUAGE PLPGSQL STABLE AS +$BODY$ +BEGIN + RAISE NOTICE 'Stable function now_s() called!'; + RETURN '2017-08-22T10:00:00'::timestamptz; +END; +$BODY$; +CREATE OR REPLACE FUNCTION now_i() +RETURNS timestamptz LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +BEGIN + RAISE NOTICE 'Immutable function now_i() called!'; + RETURN '2017-08-22T10:00:00'::timestamptz; +END; +$BODY$; +CREATE OR REPLACE FUNCTION now_v() +RETURNS timestamptz LANGUAGE PLPGSQL VOLATILE AS +$BODY$ +BEGIN + RAISE NOTICE 'Volatile function now_v() called!'; + RETURN '2017-08-22T10:00:00'::timestamptz; +END; +$BODY$; +CREATE TABLE append_test(time timestamptz, temp float, colorid integer); +SELECT create_hypertable('append_test', 'time', chunk_time_interval => 2628000000000); +psql:include/append_load.sql:35: NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------------- + (1,public,append_test,t) +(1 row) + +-- create three chunks +INSERT INTO append_test VALUES ('2017-03-22T09:18:22', 23.5, 1), + ('2017-03-22T09:18:23', 21.5, 1), + ('2017-05-22T09:18:22', 36.2, 2), + ('2017-05-22T09:18:23', 15.2, 2), + ('2017-08-22T09:18:22', 34.1, 3); +-- Create another hypertable to join with +CREATE TABLE join_test(time timestamptz, temp float, colorid integer); +SELECT create_hypertable('join_test', 'time', chunk_time_interval => 2628000000000); +psql:include/append_load.sql:46: NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------ + (2,public,join_test,t) +(1 row) + +INSERT INTO join_test VALUES ('2017-01-22T09:18:22', 15.2, 1), + ('2017-02-22T09:18:22', 24.5, 2), + ('2017-08-22T09:18:22', 23.1, 3); +-- create hypertable with DATE time dimension +CREATE TABLE metrics_date(time DATE NOT NULL); +SELECT create_hypertable('metrics_date','time'); + create_hypertable +--------------------------- + (3,public,metrics_date,t) +(1 row) + +INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date, '2000-02-01'::date, '5m'::interval); +ANALYZE metrics_date; +-- create hypertable with TIMESTAMP time dimension +CREATE TABLE metrics_timestamp(time TIMESTAMP NOT NULL); +SELECT create_hypertable('metrics_timestamp','time'); + create_hypertable +-------------------------------- + (4,public,metrics_timestamp,t) +(1 row) + +INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::date, '2000-02-01'::date, '5m'::interval); +ANALYZE metrics_timestamp; +-- create hypertable with TIMESTAMPTZ time dimension +CREATE TABLE metrics_timestamptz(time TIMESTAMPTZ NOT NULL, device_id INT NOT NULL); +CREATE INDEX ON metrics_timestamptz(device_id,time); +SELECT create_hypertable('metrics_timestamptz','time'); + create_hypertable +---------------------------------- + (5,public,metrics_timestamptz,t) +(1 row) + +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::date, '2000-02-01'::date, '5m'::interval), 1; +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::date, '2000-02-01'::date, '5m'::interval), 2; +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::date, '2000-02-01'::date, '5m'::interval), 3; +ANALYZE metrics_timestamptz; +-- create space partitioned hypertable +CREATE TABLE metrics_space(time timestamptz NOT NULL, device_id int NOT NULL, v1 float, v2 float, v3 text); +SELECT create_hypertable('metrics_space','time','device_id',3); + create_hypertable +---------------------------- + (6,public,metrics_space,t) +(1 row) + +INSERT INTO metrics_space +SELECT time, device_id, device_id + 0.25, device_id + 0.75, device_id +FROM generate_series('2000-01-01'::timestamptz, '2000-01-14'::timestamptz, '5m'::interval) g1(time), + generate_series(1,10,1) g2(device_id) +ORDER BY time, device_id; +ANALYZE metrics_space; +-- test ChunkAppend projection #2661 +CREATE TABLE i2661 ( + machine_id int4 NOT NULL, + "name" varchar(255) NOT NULL, + "timestamp" timestamptz NOT NULL, + "first" float4 NULL +); +SELECT create_hypertable('i2661', 'timestamp'); + create_hypertable +-------------------- + (7,public,i2661,t) +(1 row) + +INSERT INTO i2661 SELECT 1, 'speed', generate_series('2019-12-31 00:00:00', '2020-01-10 00:00:00', '2m'::interval), 0; +ANALYZE i2661; +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- canary for results diff +-- this should be the only output of the results diff +SELECT setting, current_setting(setting) AS value from (VALUES ('timescaledb.enable_optimizations'),('timescaledb.enable_chunk_append')) v(setting); + setting | value +----------------------------------+------- + timescaledb.enable_optimizations | on + timescaledb.enable_chunk_append | on +(2 rows) + +-- query should exclude all chunks with optimization on +:PREFIX +SELECT * FROM append_test WHERE time > now_s() + '1 month' +ORDER BY time DESC; +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:12: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------ + Custom Scan (ChunkAppend) on append_test (actual rows=0 loops=1) + Order: append_test."time" DESC + Chunks excluded during startup: 3 +(3 rows) + +--query should exclude all chunks and be a MergeAppend +:PREFIX +SELECT * FROM append_test WHERE time > now_s() + '1 month' +ORDER BY time DESC limit 1; +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:17: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------------ + Limit (actual rows=0 loops=1) + -> Custom Scan (ChunkAppend) on append_test (actual rows=0 loops=1) + Order: append_test."time" DESC + Chunks excluded during startup: 3 +(4 rows) + +-- when optimized, the plan should be a constraint-aware append and +-- cover only one chunk. It should be a backward index scan due to +-- descending index on time. Should also skip the main table, since it +-- cannot hold tuples +:PREFIX +SELECT * FROM append_test WHERE time > now_s() - interval '2 months'; +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:24: NOTICE: Stable function now_s() called! + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on append_test (actual rows=1 loops=1) + Chunks excluded during startup: 2 + -> Index Scan using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 2 mons'::interval)) +(4 rows) + +-- adding ORDER BY and LIMIT should turn the plan into an optimized +-- ordered append plan +:PREFIX +SELECT * FROM append_test WHERE time > now_s() - interval '2 months' +ORDER BY time LIMIT 3; +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:30: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on append_test (actual rows=1 loops=1) + Order: append_test."time" + Chunks excluded during startup: 2 + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 2 mons'::interval)) +(6 rows) + +-- no optimized plan for queries with restrictions that can be +-- constified at planning time. Regular planning-time constraint +-- exclusion should occur. +:PREFIX +SELECT * FROM append_test WHERE time > now_i() - interval '2 months' +ORDER BY time; +psql:include/append_query.sql:37: NOTICE: Immutable function now_i() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on append_test (actual rows=1 loops=1) + Order: append_test."time" + Chunks excluded during startup: 2 + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > ('Tue Aug 22 10:00:00 2017 PDT'::timestamp with time zone - '@ 2 mons'::interval)) +(5 rows) + +-- currently, we cannot distinguish between stable and volatile +-- functions as far as applying our modified plan. However, volatile +-- function should not be pre-evaluated to constants, so no chunk +-- exclusion should occur. +:PREFIX +SELECT * FROM append_test WHERE time > now_v() - interval '2 months' +ORDER BY time; +psql:include/append_query.sql:45: NOTICE: Volatile function now_v() called! +psql:include/append_query.sql:45: NOTICE: Volatile function now_v() called! +psql:include/append_query.sql:45: NOTICE: Volatile function now_v() called! +psql:include/append_query.sql:45: NOTICE: Volatile function now_v() called! +psql:include/append_query.sql:45: NOTICE: Volatile function now_v() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on append_test (actual rows=1 loops=1) + Order: append_test."time" + Chunks excluded during startup: 0 + -> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk (actual rows=0 loops=1) + Filter: ("time" > (now_v() - '@ 2 mons'::interval)) + Rows Removed by Filter: 2 + -> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk (actual rows=0 loops=1) + Filter: ("time" > (now_v() - '@ 2 mons'::interval)) + Rows Removed by Filter: 2 + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Filter: ("time" > (now_v() - '@ 2 mons'::interval)) +(11 rows) + +-- prepared statement output should be the same regardless of +-- optimizations +PREPARE query_opt AS +SELECT * FROM append_test WHERE time > now_s() - interval '2 months' +ORDER BY time; +:PREFIX EXECUTE query_opt; +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:53: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on append_test (actual rows=1 loops=1) + Order: append_test."time" + Chunks excluded during startup: 2 + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 2 mons'::interval)) +(5 rows) + +DEALLOCATE query_opt; +-- aggregates should produce same output +:PREFIX +SELECT date_trunc('year', time) t, avg(temp) FROM append_test +WHERE time > now_s() - interval '4 months' +GROUP BY t +ORDER BY t DESC; +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:62: NOTICE: Stable function now_s() called! + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + GroupAggregate (actual rows=1 loops=1) + Group Key: (date_trunc('year'::text, append_test."time")) + -> Custom Scan (ChunkAppend) on append_test (actual rows=3 loops=1) + Order: date_trunc('year'::text, append_test."time") DESC + Chunks excluded during startup: 1 + -> Index Scan using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 4 mons'::interval)) + -> Index Scan using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk (actual rows=2 loops=1) + Index Cond: ("time" > (now_s() - '@ 4 mons'::interval)) +(9 rows) + +-- querying outside the time range should return nothing. This tests +-- that ConstraintAwareAppend can handle the case when an Append node +-- is turned into a Result node due to no children +:PREFIX +SELECT date_trunc('year', time) t, avg(temp) +FROM append_test +WHERE time < '2016-03-22' +AND date_part('dow', time) between 1 and 5 +GROUP BY t +ORDER BY t DESC; + QUERY PLAN +------------------------------------------------------------------------------ + GroupAggregate (actual rows=0 loops=1) + Group Key: (date_trunc('year'::text, "time")) + -> Sort (actual rows=0 loops=1) + Sort Key: (date_trunc('year'::text, "time")) DESC + Sort Method: quicksort + -> Custom Scan (ChunkAppend) on append_test (actual rows=0 loops=1) + Chunks excluded during startup: 0 +(7 rows) + +-- a parameterized query can safely constify params, so won't be +-- optimized by constraint-aware append since regular constraint +-- exclusion works just fine +PREPARE query_param AS +SELECT * FROM append_test WHERE time > $1 ORDER BY time; +:PREFIX +EXECUTE query_param(now_s() - interval '2 months'); +psql:include/append_query.sql:82: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------- + Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > 'Thu Jun 22 10:00:00 2017 PDT'::timestamp with time zone) +(2 rows) + +DEALLOCATE query_param; +--test with cte +:PREFIX +WITH data AS ( + SELECT time_bucket(INTERVAL '30 day', TIME) AS btime, AVG(temp) AS VALUE + FROM append_test + WHERE + TIME > now_s() - INTERVAL '400 day' + AND colorid > 0 + GROUP BY btime +), +period AS ( + SELECT time_bucket(INTERVAL '30 day', TIME) AS btime + FROM GENERATE_SERIES('2017-03-22T01:01:01', '2017-08-23T01:01:01', INTERVAL '30 day') TIME + ) +SELECT period.btime, VALUE + FROM period + LEFT JOIN DATA USING (btime) + ORDER BY period.btime; +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:102: NOTICE: Stable function now_s() called! + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------- + Sort (actual rows=6 loops=1) + Sort Key: (time_bucket('@ 30 days'::interval, "time"."time")) + Sort Method: quicksort + -> Hash Left Join (actual rows=6 loops=1) + Hash Cond: (time_bucket('@ 30 days'::interval, "time"."time") = data.btime) + -> Function Scan on generate_series "time" (actual rows=6 loops=1) + -> Hash (actual rows=3 loops=1) + Buckets: 1024 Batches: 1 + -> Subquery Scan on data (actual rows=3 loops=1) + -> HashAggregate (actual rows=3 loops=1) + Group Key: time_bucket('@ 30 days'::interval, append_test."time") + Batches: 1 + -> Custom Scan (ChunkAppend) on append_test (actual rows=5 loops=1) + Chunks excluded during startup: 0 + -> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk (actual rows=2 loops=1) + Index Cond: ("time" > (now_s() - '@ 400 days'::interval)) + Filter: (colorid > 0) + -> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk (actual rows=2 loops=1) + Index Cond: ("time" > (now_s() - '@ 400 days'::interval)) + Filter: (colorid > 0) + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 400 days'::interval)) + Filter: (colorid > 0) +(23 rows) + +WITH data AS ( + SELECT time_bucket(INTERVAL '30 day', TIME) AS btime, AVG(temp) AS VALUE + FROM append_test + WHERE + TIME > now_s() - INTERVAL '400 day' + AND colorid > 0 + GROUP BY btime +), +period AS ( + SELECT time_bucket(INTERVAL '30 day', TIME) AS btime + FROM GENERATE_SERIES('2017-03-22T01:01:01', '2017-08-23T01:01:01', INTERVAL '30 day') TIME + ) +SELECT period.btime, VALUE + FROM period + LEFT JOIN DATA USING (btime) + ORDER BY period.btime; +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:119: NOTICE: Stable function now_s() called! + btime | value +------------------------------+------- + Fri Mar 03 16:00:00 2017 PST | 22.5 + Sun Apr 02 17:00:00 2017 PDT | + Tue May 02 17:00:00 2017 PDT | 25.7 + Thu Jun 01 17:00:00 2017 PDT | + Sat Jul 01 17:00:00 2017 PDT | + Mon Jul 31 17:00:00 2017 PDT | 34.1 +(6 rows) + +-- force nested loop join with no materialization. This tests that the +-- inner ConstraintAwareScan supports resetting its scan for every +-- iteration of the outer relation loop +set enable_hashjoin = 'off'; +set enable_mergejoin = 'off'; +set enable_material = 'off'; +:PREFIX +SELECT * FROM append_test a INNER JOIN join_test j ON (a.colorid = j.colorid) +WHERE a.time > now_s() - interval '3 hours' AND j.time > now_s() - interval '3 hours'; +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! +psql:include/append_query.sql:130: NOTICE: Stable function now_s() called! + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Nested Loop (actual rows=1 loops=1) + Join Filter: (a.colorid = j.colorid) + -> Custom Scan (ChunkAppend) on append_test a (actual rows=1 loops=1) + Chunks excluded during startup: 2 + -> Index Scan using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk a_1 (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 3 hours'::interval)) + -> Custom Scan (ChunkAppend) on join_test j (actual rows=1 loops=1) + Chunks excluded during startup: 2 + -> Index Scan using _hyper_2_6_chunk_join_test_time_idx on _hyper_2_6_chunk j_1 (actual rows=1 loops=1) + Index Cond: ("time" > (now_s() - '@ 3 hours'::interval)) +(10 rows) + +reset enable_hashjoin; +reset enable_mergejoin; +reset enable_material; +-- test constraint_exclusion with date time dimension and DATE/TIMESTAMP/TIMESTAMPTZ constraints +-- the queries should all have 3 chunks +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::date ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::timestamp ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1441 +(12 rows) + +-- test Const OP Var +-- the queries should all have 3 chunks +:PREFIX SELECT * FROM metrics_date WHERE '2000-01-15'::date < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_date WHERE '2000-01-15'::timestamp < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_date WHERE '2000-01-15'::timestamptz < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_date (actual rows=4609 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_3_11_chunk_metrics_date_time_idx on _hyper_3_11_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1441 +(12 rows) + +-- test 2 constraints +-- the queries should all have 2 chunks +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::date AND time < '2000-01-21'::date ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=1440 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=288 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 288 +(8 rows) + +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::timestamp AND time < '2000-01-21'::timestamp ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=1440 loops=1) + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=288 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 288 +(8 rows) + +:PREFIX SELECT * FROM metrics_date WHERE time > '2000-01-15'::timestamptz AND time < '2000-01-21'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=1440 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_3_9_chunk_metrics_date_time_idx on _hyper_3_9_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1152 + -> Index Only Scan Backward using _hyper_3_10_chunk_metrics_date_time_idx on _hyper_3_10_chunk (actual rows=288 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 288 +(9 rows) + +-- test constraint_exclusion with timestamp time dimension and DATE/TIMESTAMP/TIMESTAMPTZ constraints +-- the queries should all have 3 chunks +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::date ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::timestamp ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::timestamptz ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1441 +(12 rows) + +-- test Const OP Var +-- the queries should all have 3 chunks +:PREFIX SELECT * FROM metrics_timestamp WHERE '2000-01-15'::date < time ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE '2000-01-15'::timestamp < time ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1441 +(11 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE '2000-01-15'::timestamptz < time ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=4896 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=2016 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 2016 + -> Index Only Scan Backward using _hyper_4_16_chunk_metrics_timestamp_time_idx on _hyper_4_16_chunk (actual rows=1441 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1441 +(12 rows) + +-- test 2 constraints +-- the queries should all have 2 chunks +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::date AND time < '2000-01-21'::date ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=1727 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=288 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 288 +(8 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::timestamp AND time < '2000-01-21'::timestamp ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=1727 loops=1) + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=288 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 288 +(8 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE time > '2000-01-15'::timestamptz AND time < '2000-01-21'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=1727 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_4_14_chunk_metrics_timestamp_time_idx on _hyper_4_14_chunk (actual rows=1439 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1439 + -> Index Only Scan Backward using _hyper_4_15_chunk_metrics_timestamp_time_idx on _hyper_4_15_chunk (actual rows=288 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 288 +(9 rows) + +-- test constraint_exclusion with timestamptz time dimension and DATE/TIMESTAMP/TIMESTAMPTZ constraints +-- the queries should all have 3 chunks +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::date ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 4611 +(12 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::timestamp ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 4611 +(12 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 4611 +(11 rows) + +-- test Const OP Var +-- the queries should all have 3 chunks +:PREFIX SELECT time FROM metrics_timestamptz WHERE '2000-01-15'::date < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > '01-15-2000'::date) + Heap Fetches: 4611 +(12 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE '2000-01-15'::timestamp < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 2 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 4611 +(12 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE '2000-01-15'::timestamptz < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=14688 loops=1) + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=6048 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=4611 loops=1) + Index Cond: ("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 4611 +(11 rows) + +-- test 2 constraints +-- the queries should all have 2 chunks +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::date AND time < '2000-01-21'::date ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=5181 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > '01-15-2000'::date) AND ("time" < '01-21-2000'::date)) + Heap Fetches: 1152 +(9 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::timestamp AND time < '2000-01-21'::timestamp ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=5181 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1152 +(9 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > '2000-01-15'::timestamptz AND time < '2000-01-21'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=5181 loops=1) + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (actual rows=4029 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 4029 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (actual rows=1152 loops=1) + Index Cond: (("time" > 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Fri Jan 21 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1152 +(8 rows) + +-- test constraint_exclusion with space partitioning and DATE/TIMESTAMP/TIMESTAMPTZ constraints +-- exclusion for constraints with non-matching datatypes not working for space partitioning atm +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::date ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamp ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 770 +(24 rows) + +-- test Const OP Var +-- exclusion for constraints with non-matching datatypes not working for space partitioning atm +:PREFIX SELECT time FROM metrics_space WHERE '2000-01-10'::date < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > '01-10-2000'::date) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE '2000-01-10'::timestamp < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE '2000-01-10'::timestamptz < time ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 770 +(24 rows) + +-- test 2 constraints +-- exclusion for constraints with non-matching datatypes not working for space partitioning atm +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::date AND time < '2000-01-15'::date ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: (("time" > '01-10-2000'::date) AND ("time" < '01-15-2000'::date)) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamp AND time < '2000-01-15'::timestamp ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 0 + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000'::timestamp without time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000'::timestamp without time zone)) + Heap Fetches: 770 +(35 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz AND time < '2000-01-15'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=11520 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=7670 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=3068 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 3068 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=1534 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1534 + -> Merge Append (actual rows=3850 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=1540 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 1540 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=770 loops=1) + Index Cond: (("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Sat Jan 15 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 770 +(24 rows) + +-- test filtering on space partition +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz AND device_id = 1 ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=1152 loops=1) + Order: metrics_space."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_device_id_time_idx on _hyper_6_25_chunk (actual rows=767 loops=1) + Index Cond: ((device_id = 1) AND ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 767 + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_device_id_time_idx on _hyper_6_28_chunk (actual rows=385 loops=1) + Index Cond: ((device_id = 1) AND ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 385 +(8 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz AND device_id IN (1,2) ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=2304 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=1534 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=767 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = ANY ('{1,2}'::integer[])) + Rows Removed by Filter: 2301 + -> Index Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=767 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = ANY ('{1,2}'::integer[])) + Rows Removed by Filter: 2301 + -> Merge Append (actual rows=770 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=385 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = ANY ('{1,2}'::integer[])) + Rows Removed by Filter: 1155 + -> Index Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=385 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = ANY ('{1,2}'::integer[])) + Rows Removed by Filter: 1155 +(22 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz AND device_id IN (VALUES(1)) ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=1152 loops=1) + Order: metrics_space."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_device_id_time_idx on _hyper_6_25_chunk (actual rows=767 loops=1) + Index Cond: ((device_id = 1) AND ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 767 + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_device_id_time_idx on _hyper_6_28_chunk (actual rows=385 loops=1) + Index Cond: ((device_id = 1) AND ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Heap Fetches: 385 +(8 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > '2000-01-10'::timestamptz AND v3 IN (VALUES('1')) ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=1152 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=767 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=767 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 2301 + -> Index Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 3068 + -> Index Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 1534 + -> Merge Append (actual rows=385 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=385 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 1155 + -> Index Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 1540 + -> Index Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=0 loops=1) + Index Cond: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (v3 = '1'::text) + Rows Removed by Filter: 770 +(30 rows) + +:PREFIX SELECT * FROM metrics_space +WHERE time = (VALUES ('2019-12-24' at time zone 'UTC')) + AND v3 NOT IN (VALUES ('1')); + QUERY PLAN +------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=0 loops=1) + Chunks excluded during startup: 0 + Chunks excluded during runtime: 9 + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Index Scan using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + SubPlan 2 + -> Result (never executed) + -> Index Scan using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) + -> Index Scan using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (never executed) + Index Cond: ("time" = $0) + Filter: (NOT (hashed SubPlan 2)) +(34 rows) + +-- test CURRENT_DATE +-- should be 0 chunks +:PREFIX SELECT time FROM metrics_date WHERE time > CURRENT_DATE ORDER BY time; + QUERY PLAN +------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=0 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamp WHERE time > CURRENT_DATE ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=0 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > CURRENT_DATE ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=0 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > CURRENT_DATE ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=0 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_DATE) + Heap Fetches: 0 +(35 rows) + +-- test CURRENT_TIMESTAMP +-- should be 0 chunks +:PREFIX SELECT time FROM metrics_date WHERE time > CURRENT_TIMESTAMP ORDER BY time; + QUERY PLAN +------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=0 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamp WHERE time > CURRENT_TIMESTAMP ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=0 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > CURRENT_TIMESTAMP ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=0 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > CURRENT_TIMESTAMP ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=0 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=0 loops=1) + Index Cond: ("time" > CURRENT_TIMESTAMP) + Heap Fetches: 0 +(35 rows) + +-- test now() +-- should be 0 chunks +:PREFIX SELECT time FROM metrics_date WHERE time > now() ORDER BY time; + QUERY PLAN +------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date (actual rows=0 loops=1) + Order: metrics_date."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamp WHERE time > now() ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_timestamp (actual rows=0 loops=1) + Order: metrics_timestamp."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time > now() ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=0 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 5 +(3 rows) + +:PREFIX SELECT time FROM metrics_space WHERE time > now() ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_space (actual rows=0 loops=1) + Order: metrics_space."time" + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_22_chunk."time" + -> Index Only Scan Backward using _hyper_6_22_chunk_metrics_space_time_idx on _hyper_6_22_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_23_chunk_metrics_space_time_idx on _hyper_6_23_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_24_chunk_metrics_space_time_idx on _hyper_6_24_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_25_chunk."time" + -> Index Only Scan Backward using _hyper_6_25_chunk_metrics_space_time_idx on _hyper_6_25_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_26_chunk_metrics_space_time_idx on _hyper_6_26_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_27_chunk_metrics_space_time_idx on _hyper_6_27_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Merge Append (actual rows=0 loops=1) + Sort Key: _hyper_6_28_chunk."time" + -> Index Only Scan Backward using _hyper_6_28_chunk_metrics_space_time_idx on _hyper_6_28_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_29_chunk_metrics_space_time_idx on _hyper_6_29_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_6_30_chunk_metrics_space_time_idx on _hyper_6_30_chunk (actual rows=0 loops=1) + Index Cond: ("time" > now()) + Heap Fetches: 0 +(35 rows) + +-- query with tablesample and planner exclusion +:PREFIX +SELECT * FROM metrics_date TABLESAMPLE BERNOULLI(5) REPEATABLE(0) +WHERE time > '2000-01-15' +ORDER BY time DESC; + QUERY PLAN +---------------------------------------------------------------------------------- + Sort (actual rows=217 loops=1) + Sort Key: _hyper_3_11_chunk."time" DESC + Sort Method: quicksort + -> Append (actual rows=217 loops=1) + -> Sample Scan on _hyper_3_11_chunk (actual rows=72 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > '01-15-2000'::date) + -> Sample Scan on _hyper_3_10_chunk (actual rows=94 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > '01-15-2000'::date) + -> Sample Scan on _hyper_3_9_chunk (actual rows=51 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > '01-15-2000'::date) + Rows Removed by Filter: 43 +(14 rows) + +-- query with tablesample and startup exclusion +:PREFIX +SELECT * FROM metrics_date TABLESAMPLE BERNOULLI(5) REPEATABLE(0) +WHERE time > '2000-01-15'::text::date +ORDER BY time DESC; + QUERY PLAN +---------------------------------------------------------------------------------- + Sort (actual rows=217 loops=1) + Sort Key: metrics_date."time" DESC + Sort Method: quicksort + -> Custom Scan (ChunkAppend) on metrics_date (actual rows=217 loops=1) + Chunks excluded during startup: 2 + -> Sample Scan on _hyper_3_11_chunk (actual rows=72 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > ('2000-01-15'::cstring)::date) + -> Sample Scan on _hyper_3_10_chunk (actual rows=94 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > ('2000-01-15'::cstring)::date) + -> Sample Scan on _hyper_3_9_chunk (actual rows=51 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > ('2000-01-15'::cstring)::date) + Rows Removed by Filter: 43 +(15 rows) + +-- query with tablesample, space partitioning and planner exclusion +:PREFIX +SELECT * FROM metrics_space TABLESAMPLE BERNOULLI(5) REPEATABLE(0) +WHERE time > '2000-01-10'::timestamptz +ORDER BY time DESC, device_id; + QUERY PLAN +------------------------------------------------------------------------------------------- + Sort (actual rows=522 loops=1) + Sort Key: _hyper_6_30_chunk."time" DESC, _hyper_6_30_chunk.device_id + Sort Method: quicksort + -> Append (actual rows=522 loops=1) + -> Sample Scan on _hyper_6_30_chunk (actual rows=35 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Sample Scan on _hyper_6_29_chunk (actual rows=61 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Sample Scan on _hyper_6_28_chunk (actual rows=61 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Sample Scan on _hyper_6_27_chunk (actual rows=65 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Rows Removed by Filter: 113 + -> Sample Scan on _hyper_6_26_chunk (actual rows=150 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Rows Removed by Filter: 218 + -> Sample Scan on _hyper_6_25_chunk (actual rows=150 loops=1) + Sampling: bernoulli ('5'::real) REPEATABLE ('0'::double precision) + Filter: ("time" > 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Rows Removed by Filter: 218 +(25 rows) + +-- test runtime exclusion +-- test runtime exclusion with LATERAL and 2 hypertables +:PREFIX SELECT m1.time, m2.time FROM metrics_timestamptz m1 LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m2 WHERE m1.time = m2.time LIMIT 1) m2 ON true ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------ + Nested Loop Left Join (actual rows=26787 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=26787 loops=1) + Order: m1."time" + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m1_1 (actual rows=4032 loops=1) + Heap Fetches: 4032 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_2 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m1_3 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m1_4 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m1_5 (actual rows=4611 loops=1) + Heap Fetches: 4611 + -> Limit (actual rows=1 loops=26787) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m2 (actual rows=1 loops=26787) + Chunks excluded during runtime: 4 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m2_1 (actual rows=1 loops=4032) + Index Cond: ("time" = m1."time") + Heap Fetches: 4032 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m2_2 (actual rows=1 loops=6048) + Index Cond: ("time" = m1."time") + Heap Fetches: 6048 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m2_3 (actual rows=1 loops=6048) + Index Cond: ("time" = m1."time") + Heap Fetches: 6048 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m2_4 (actual rows=1 loops=6048) + Index Cond: ("time" = m1."time") + Heap Fetches: 6048 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m2_5 (actual rows=1 loops=4611) + Index Cond: ("time" = m1."time") + Heap Fetches: 4611 +(31 rows) + +-- test runtime exclusion and startup exclusions +:PREFIX SELECT m1.time, m2.time FROM metrics_timestamptz m1 LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m2 WHERE m1.time = m2.time AND m2.time < '2000-01-10'::text::timestamptz LIMIT 1) m2 ON true ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------ + Nested Loop Left Join (actual rows=26787 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=26787 loops=1) + Order: m1."time" + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m1_1 (actual rows=4032 loops=1) + Heap Fetches: 4032 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_2 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m1_3 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m1_4 (actual rows=6048 loops=1) + Heap Fetches: 6048 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m1_5 (actual rows=4611 loops=1) + Heap Fetches: 4611 + -> Limit (actual rows=0 loops=26787) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m2 (actual rows=0 loops=26787) + Chunks excluded during startup: 3 + Chunks excluded during runtime: 1 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m2_1 (actual rows=1 loops=4032) + Index Cond: (("time" < ('2000-01-10'::cstring)::timestamp with time zone) AND ("time" = m1."time")) + Heap Fetches: 4032 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m2_2 (actual rows=1 loops=6048) + Index Cond: (("time" < ('2000-01-10'::cstring)::timestamp with time zone) AND ("time" = m1."time")) + Heap Fetches: 3744 +(23 rows) + +-- test runtime exclusion does not activate for constraints on non-partitioning columns +-- should not use runtime exclusion +:PREFIX SELECT * FROM append_test a LEFT JOIN LATERAL(SELECT * FROM join_test j WHERE a.colorid = j.colorid ORDER BY time DESC LIMIT 1) j ON true ORDER BY a.time LIMIT 1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Nested Loop Left Join (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on append_test a (actual rows=1 loops=1) + Order: a."time" + -> Index Scan Backward using _hyper_1_1_chunk_append_test_time_idx on _hyper_1_1_chunk a_1 (actual rows=1 loops=1) + -> Index Scan Backward using _hyper_1_2_chunk_append_test_time_idx on _hyper_1_2_chunk a_2 (never executed) + -> Index Scan Backward using _hyper_1_3_chunk_append_test_time_idx on _hyper_1_3_chunk a_3 (never executed) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on join_test j (actual rows=1 loops=1) + Order: j."time" DESC + -> Index Scan using _hyper_2_6_chunk_join_test_time_idx on _hyper_2_6_chunk j_1 (actual rows=0 loops=1) + Filter: (a.colorid = colorid) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_2_5_chunk_join_test_time_idx on _hyper_2_5_chunk j_2 (actual rows=0 loops=1) + Filter: (a.colorid = colorid) + Rows Removed by Filter: 1 + -> Index Scan using _hyper_2_4_chunk_join_test_time_idx on _hyper_2_4_chunk j_3 (actual rows=1 loops=1) + Filter: (a.colorid = colorid) +(18 rows) + +-- test runtime exclusion with LATERAL and generate_series +:PREFIX SELECT g.time FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g(time) LEFT JOIN LATERAL(SELECT time FROM metrics_timestamptz m WHERE m.time=g.time LIMIT 1) m ON true; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop Left Join (actual rows=32 loops=1) + -> Function Scan on generate_series g (actual rows=32 loops=1) + -> Limit (actual rows=1 loops=32) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m (actual rows=1 loops=32) + Chunks excluded during runtime: 4 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1 (actual rows=1 loops=5) + Index Cond: ("time" = g."time") + Heap Fetches: 5 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2 (actual rows=1 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 7 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3 (actual rows=1 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 7 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4 (actual rows=1 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 7 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5 (actual rows=1 loops=6) + Index Cond: ("time" = g."time") + Heap Fetches: 6 +(20 rows) + +:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time=g.time) m ON true; + QUERY PLAN +-------------------------------------------------------------------------------- + Hash Join (actual rows=96 loops=1) + Hash Cond: (g."time" = m_1."time") + -> Function Scan on generate_series g (actual rows=32 loops=1) + -> Hash (actual rows=26787 loops=1) + Buckets: 32768 Batches: 1 + -> Append (actual rows=26787 loops=1) + -> Seq Scan on _hyper_5_17_chunk m_1 (actual rows=4032 loops=1) + -> Seq Scan on _hyper_5_18_chunk m_2 (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_19_chunk m_3 (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_20_chunk m_4 (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_21_chunk m_5 (actual rows=4611 loops=1) +(11 rows) + +:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time=g.time ORDER BY time) m ON true; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Nested Loop (actual rows=96 loops=1) + -> Function Scan on generate_series g (actual rows=32 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m (actual rows=3 loops=32) + Chunks excluded during runtime: 4 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1 (actual rows=3 loops=5) + Index Cond: ("time" = g."time") + Heap Fetches: 15 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2 (actual rows=3 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 21 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3 (actual rows=3 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 21 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4 (actual rows=3 loops=7) + Index Cond: ("time" = g."time") + Heap Fetches: 21 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5 (actual rows=3 loops=6) + Index Cond: ("time" = g."time") + Heap Fetches: 18 +(19 rows) + +:PREFIX SELECT * FROM generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval) AS g(time) INNER JOIN LATERAL (SELECT time FROM metrics_timestamptz m WHERE time>g.time + '1 day' ORDER BY time LIMIT 1) m ON true; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop (actual rows=30 loops=1) + -> Function Scan on generate_series g (actual rows=32 loops=1) + -> Limit (actual rows=1 loops=32) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m (actual rows=1 loops=32) + Order: m."time" + Chunks excluded during startup: 0 + Chunks excluded during runtime: 2 + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m_1 (actual rows=1 loops=4) + Index Cond: ("time" > (g."time" + '@ 1 day'::interval)) + Heap Fetches: 4 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m_2 (actual rows=1 loops=7) + Index Cond: ("time" > (g."time" + '@ 1 day'::interval)) + Heap Fetches: 7 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m_3 (actual rows=1 loops=7) + Index Cond: ("time" > (g."time" + '@ 1 day'::interval)) + Heap Fetches: 7 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m_4 (actual rows=1 loops=7) + Index Cond: ("time" > (g."time" + '@ 1 day'::interval)) + Heap Fetches: 7 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m_5 (actual rows=1 loops=7) + Index Cond: ("time" > (g."time" + '@ 1 day'::interval)) + Heap Fetches: 5 +(22 rows) + +-- test runtime exclusion with subquery +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE m1.time=(SELECT max(time) FROM metrics_timestamptz); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=3 loops=1) + Chunks excluded during runtime: 4 + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + InitPlan 1 (returns $0) + -> Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=1 loops=1) + Order: metrics_timestamptz."time" DESC + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (actual rows=1 loops=1) + Index Cond: ("time" IS NOT NULL) + Heap Fetches: 1 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk (never executed) + Index Cond: ("time" IS NOT NULL) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m1_1 (never executed) + Index Cond: ("time" = $1) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_2 (never executed) + Index Cond: ("time" = $1) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m1_3 (never executed) + Index Cond: ("time" = $1) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m1_4 (never executed) + Index Cond: ("time" = $1) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m1_5 (actual rows=3 loops=1) + Index Cond: ("time" = $1) + Heap Fetches: 3 +(38 rows) + +-- test runtime exclusion with correlated subquery +:PREFIX SELECT m1.time, (SELECT m2.time FROM metrics_timestamptz m2 WHERE m2.time < m1.time ORDER BY m2.time DESC LIMIT 1) FROM metrics_timestamptz m1 WHERE m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=7776 loops=1) + Order: m1."time" + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m1_1 (actual rows=4032 loops=1) + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 4032 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_2 (actual rows=3744 loops=1) + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 3744 + SubPlan 1 + -> Limit (actual rows=1 loops=7776) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m2 (actual rows=1 loops=7776) + Order: m2."time" DESC + Chunks excluded during runtime: 3 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m2_1 (never executed) + Index Cond: ("time" < m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m2_2 (never executed) + Index Cond: ("time" < m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m2_3 (never executed) + Index Cond: ("time" < m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m2_4 (actual rows=1 loops=3741) + Index Cond: ("time" < m1."time") + Heap Fetches: 3741 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m2_5 (actual rows=1 loops=4035) + Index Cond: ("time" < m1."time") + Heap Fetches: 4032 +(28 rows) + +-- test EXISTS +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 WHERE EXISTS(SELECT 1 FROM metrics_timestamptz m2 WHERE m1.time < m2.time) ORDER BY m1.time DESC limit 1000; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=1000 loops=1) + -> Nested Loop Semi Join (actual rows=1000 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=1003 loops=1) + Order: m1."time" DESC + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m1_1 (actual rows=1003 loops=1) + Heap Fetches: 1003 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m1_2 (never executed) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m1_3 (never executed) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_4 (never executed) + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m1_5 (never executed) + Heap Fetches: 0 + -> Append (actual rows=1 loops=1003) + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk m2_1 (actual rows=0 loops=1003) + Index Cond: ("time" > m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m2_2 (actual rows=0 loops=1003) + Index Cond: ("time" > m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m2_3 (actual rows=0 loops=1003) + Index Cond: ("time" > m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m2_4 (actual rows=0 loops=1003) + Index Cond: ("time" > m1."time") + Heap Fetches: 0 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m2_5 (actual rows=1 loops=1003) + Index Cond: ("time" > m1."time") + Heap Fetches: 1000 +(30 rows) + +-- test constraint exclusion for subqueries with append +-- should include 2 chunks +:PREFIX SELECT time FROM (SELECT time FROM metrics_timestamptz WHERE time < '2000-01-10'::text::timestamptz ORDER BY time) m; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=7776 loops=1) + Order: metrics_timestamptz."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk (actual rows=4032 loops=1) + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + Heap Fetches: 4032 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk (actual rows=3744 loops=1) + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + Heap Fetches: 3744 +(9 rows) + +-- test constraint exclusion for subqueries with mergeappend +-- should include 2 chunks +:PREFIX SELECT device_id, time FROM (SELECT device_id, time FROM metrics_timestamptz WHERE time < '2000-01-10'::text::timestamptz ORDER BY device_id, time) m; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ConstraintAwareAppend) (actual rows=7776 loops=1) + Hypertable: metrics_timestamptz + Chunks left after exclusion: 2 + -> Merge Append (actual rows=7776 loops=1) + Sort Key: _hyper_5_17_chunk.device_id, _hyper_5_17_chunk."time" + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_17_chunk (actual rows=4032 loops=1) + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + Heap Fetches: 4032 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_18_chunk (actual rows=3744 loops=1) + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + Heap Fetches: 3744 +(11 rows) + +-- test LIMIT pushdown +-- no aggregates/window functions/SRF should pushdown limit +:PREFIX SELECT FROM metrics_timestamptz ORDER BY time LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz (actual rows=1 loops=1) + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_5_17_chunk_metrics_timestamptz_time_idx on _hyper_5_17_chunk (actual rows=1 loops=1) + Heap Fetches: 1 + -> Index Only Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk (never executed) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk (never executed) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk (never executed) + Heap Fetches: 0 + -> Index Only Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk (never executed) + Heap Fetches: 0 +(13 rows) + +-- aggregates should prevent pushdown +:PREFIX SELECT count(*) FROM metrics_timestamptz LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Aggregate (actual rows=1 loops=1) + -> Append (actual rows=26787 loops=1) + -> Seq Scan on _hyper_5_17_chunk (actual rows=4032 loops=1) + -> Seq Scan on _hyper_5_18_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_19_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_20_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_21_chunk (actual rows=4611 loops=1) +(8 rows) + +:PREFIX SELECT count(*) FROM metrics_space LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Aggregate (actual rows=1 loops=1) + -> Append (actual rows=37450 loops=1) + -> Seq Scan on _hyper_6_22_chunk (actual rows=5376 loops=1) + -> Seq Scan on _hyper_6_23_chunk (actual rows=5376 loops=1) + -> Seq Scan on _hyper_6_24_chunk (actual rows=2688 loops=1) + -> Seq Scan on _hyper_6_25_chunk (actual rows=8064 loops=1) + -> Seq Scan on _hyper_6_26_chunk (actual rows=8064 loops=1) + -> Seq Scan on _hyper_6_27_chunk (actual rows=4032 loops=1) + -> Seq Scan on _hyper_6_28_chunk (actual rows=1540 loops=1) + -> Seq Scan on _hyper_6_29_chunk (actual rows=1540 loops=1) + -> Seq Scan on _hyper_6_30_chunk (actual rows=770 loops=1) +(12 rows) + +-- HAVING should prevent pushdown +:PREFIX SELECT 1 FROM metrics_timestamptz HAVING count(*) > 1 LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Aggregate (actual rows=1 loops=1) + Filter: (count(*) > 1) + -> Append (actual rows=26787 loops=1) + -> Seq Scan on _hyper_5_17_chunk (actual rows=4032 loops=1) + -> Seq Scan on _hyper_5_18_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_19_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_20_chunk (actual rows=6048 loops=1) + -> Seq Scan on _hyper_5_21_chunk (actual rows=4611 loops=1) +(9 rows) + +:PREFIX SELECT 1 FROM metrics_space HAVING count(*) > 1 LIMIT 1; + QUERY PLAN +---------------------------------------------------------------------------- + Limit (actual rows=1 loops=1) + -> Aggregate (actual rows=1 loops=1) + Filter: (count(*) > 1) + -> Append (actual rows=37450 loops=1) + -> Seq Scan on _hyper_6_22_chunk (actual rows=5376 loops=1) + -> Seq Scan on _hyper_6_23_chunk (actual rows=5376 loops=1) + -> Seq Scan on _hyper_6_24_chunk (actual rows=2688 loops=1) + -> Seq Scan on _hyper_6_25_chunk (actual rows=8064 loops=1) + -> Seq Scan on _hyper_6_26_chunk (actual rows=8064 loops=1) + -> Seq Scan on _hyper_6_27_chunk (actual rows=4032 loops=1) + -> Seq Scan on _hyper_6_28_chunk (actual rows=1540 loops=1) + -> Seq Scan on _hyper_6_29_chunk (actual rows=1540 loops=1) + -> Seq Scan on _hyper_6_30_chunk (actual rows=770 loops=1) +(13 rows) + +-- DISTINCT should prevent pushdown +SET enable_hashagg TO false; +:PREFIX SELECT DISTINCT device_id FROM metrics_timestamptz ORDER BY device_id LIMIT 3; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=3 loops=1) + -> Unique (actual rows=3 loops=1) + -> Merge Append (actual rows=17859 loops=1) + Sort Key: _hyper_5_17_chunk.device_id + -> Index Only Scan using _hyper_5_17_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_17_chunk (actual rows=2689 loops=1) + Heap Fetches: 2689 + -> Index Only Scan using _hyper_5_18_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_18_chunk (actual rows=4033 loops=1) + Heap Fetches: 4033 + -> Index Only Scan using _hyper_5_19_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_19_chunk (actual rows=4033 loops=1) + Heap Fetches: 4033 + -> Index Only Scan using _hyper_5_20_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_20_chunk (actual rows=4033 loops=1) + Heap Fetches: 4033 + -> Index Only Scan using _hyper_5_21_chunk_metrics_timestamptz_device_id_time_idx on _hyper_5_21_chunk (actual rows=3075 loops=1) + Heap Fetches: 3075 +(14 rows) + +:PREFIX SELECT DISTINCT device_id FROM metrics_space ORDER BY device_id LIMIT 3; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=3 loops=1) + -> Unique (actual rows=3 loops=1) + -> Merge Append (actual rows=7491 loops=1) + Sort Key: _hyper_6_22_chunk.device_id + -> Index Only Scan using _hyper_6_22_chunk_metrics_space_device_id_time_idx on _hyper_6_22_chunk (actual rows=1345 loops=1) + Heap Fetches: 1345 + -> Index Only Scan using _hyper_6_23_chunk_metrics_space_device_id_time_idx on _hyper_6_23_chunk (actual rows=1345 loops=1) + Heap Fetches: 1345 + -> Index Only Scan using _hyper_6_24_chunk_metrics_space_device_id_time_idx on _hyper_6_24_chunk (actual rows=1 loops=1) + Heap Fetches: 1 + -> Index Only Scan using _hyper_6_25_chunk_metrics_space_device_id_time_idx on _hyper_6_25_chunk (actual rows=2017 loops=1) + Heap Fetches: 2017 + -> Index Only Scan using _hyper_6_26_chunk_metrics_space_device_id_time_idx on _hyper_6_26_chunk (actual rows=2017 loops=1) + Heap Fetches: 2017 + -> Index Only Scan using _hyper_6_27_chunk_metrics_space_device_id_time_idx on _hyper_6_27_chunk (actual rows=1 loops=1) + Heap Fetches: 1 + -> Index Only Scan using _hyper_6_28_chunk_metrics_space_device_id_time_idx on _hyper_6_28_chunk (actual rows=386 loops=1) + Heap Fetches: 386 + -> Index Only Scan using _hyper_6_29_chunk_metrics_space_device_id_time_idx on _hyper_6_29_chunk (actual rows=386 loops=1) + Heap Fetches: 386 + -> Index Only Scan using _hyper_6_30_chunk_metrics_space_device_id_time_idx on _hyper_6_30_chunk (actual rows=1 loops=1) + Heap Fetches: 1 +(22 rows) + +RESET enable_hashagg; +-- JOINs should prevent pushdown +-- when LIMIT gets pushed to a Sort node it will switch to top-N heapsort +-- if more tuples then LIMIT are requested this will trigger an error +-- to trigger this we need a Sort node that is below ChunkAppend +CREATE TABLE join_limit (time timestamptz, device_id int); +SELECT table_name FROM create_hypertable('join_limit','time',create_default_indexes:=false); +psql:include/append_query.sql:315: NOTICE: adding not-null constraint to column "time" + table_name +------------ + join_limit +(1 row) + +CREATE INDEX ON join_limit(time,device_id); +INSERT INTO join_limit +SELECT time, device_id +FROM generate_series('2000-01-01'::timestamptz,'2000-01-21','30m') g1(time), + generate_series(1,10,1) g2(device_id) +ORDER BY time, device_id; +-- get 2nd chunk oid +SELECT tableoid AS "CHUNK_OID" FROM join_limit WHERE time > '2000-01-07' ORDER BY time LIMIT 1 +\gset +--get index name for 2nd chunk +SELECT indexrelid::regclass AS "INDEX_NAME" FROM pg_index WHERE indrelid = :CHUNK_OID +\gset +DROP INDEX :INDEX_NAME; +:PREFIX SELECT * FROM metrics_timestamptz m1 INNER JOIN join_limit m2 ON m1.time = m2.time AND m1.device_id=m2.device_id WHERE m1.time > '2000-01-07' ORDER BY m1.time, m1.device_id LIMIT 3; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Limit (actual rows=3 loops=1) + -> Merge Join (actual rows=3 loops=1) + Merge Cond: (m2."time" = m1."time") + Join Filter: (m1.device_id = m2.device_id) + Rows Removed by Join Filter: 4 + -> Custom Scan (ChunkAppend) on join_limit m2 (actual rows=3 loops=1) + Order: m2."time", m2.device_id + -> Sort (actual rows=3 loops=1) + Sort Key: m2_1."time", m2_1.device_id + Sort Method: quicksort + -> Seq Scan on _hyper_8_35_chunk m2_1 (actual rows=2710 loops=1) + Filter: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + Rows Removed by Filter: 650 + -> Index Only Scan using _hyper_8_36_chunk_join_limit_time_device_id_idx on _hyper_8_36_chunk m2_2 (never executed) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 0 + -> Index Only Scan using _hyper_8_37_chunk_join_limit_time_device_id_idx on _hyper_8_37_chunk m2_3 (never executed) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + Heap Fetches: 0 + -> Materialize (actual rows=22 loops=1) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 (actual rows=19 loops=1) + Order: m1."time" + -> Index Scan Backward using _hyper_5_18_chunk_metrics_timestamptz_time_idx on _hyper_5_18_chunk m1_1 (actual rows=19 loops=1) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + -> Index Scan Backward using _hyper_5_19_chunk_metrics_timestamptz_time_idx on _hyper_5_19_chunk m1_2 (never executed) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + -> Index Scan Backward using _hyper_5_20_chunk_metrics_timestamptz_time_idx on _hyper_5_20_chunk m1_3 (never executed) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) + -> Index Scan Backward using _hyper_5_21_chunk_metrics_timestamptz_time_idx on _hyper_5_21_chunk m1_4 (never executed) + Index Cond: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone) +(30 rows) + +DROP TABLE join_limit; +-- test ChunkAppend projection #2661 +:PREFIX SELECT ts.timestamp, ht.timestamp +FROM ( + SELECT generate_series( + to_timestamp(FLOOR(EXTRACT (EPOCH FROM '2020-01-01T00:01:00Z'::timestamp) / 300) * 300) AT TIME ZONE 'UTC', + '2020-01-01T01:00:00Z', + '5 minutes'::interval + ) AS timestamp +) ts +LEFT JOIN i2661 ht ON + (FLOOR(EXTRACT (EPOCH FROM ht."timestamp") / 300) * 300 = EXTRACT (EPOCH FROM ts.timestamp)) + AND ht.timestamp > '2019-12-30T00:00:00Z'::timestamp; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Merge Left Join (actual rows=33 loops=1) + Merge Cond: ((date_part('epoch'::text, ts."timestamp")) = ((floor((date_part('epoch'::text, ht."timestamp") / '300'::double precision)) * '300'::double precision))) + -> Sort (actual rows=13 loops=1) + Sort Key: (date_part('epoch'::text, ts."timestamp")) + Sort Method: quicksort + -> Subquery Scan on ts (actual rows=13 loops=1) + -> ProjectSet (actual rows=13 loops=1) + -> Result (actual rows=1 loops=1) + -> Sort (actual rows=514 loops=1) + Sort Key: ((floor((date_part('epoch'::text, ht."timestamp") / '300'::double precision)) * '300'::double precision)) + Sort Method: quicksort + -> Custom Scan (ChunkAppend) on i2661 ht (actual rows=7201 loops=1) + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_7_31_chunk ht_1 (actual rows=1200 loops=1) + Filter: ("timestamp" > 'Mon Dec 30 00:00:00 2019'::timestamp without time zone) + -> Seq Scan on _hyper_7_32_chunk ht_2 (actual rows=5040 loops=1) + Filter: ("timestamp" > 'Mon Dec 30 00:00:00 2019'::timestamp without time zone) + -> Seq Scan on _hyper_7_33_chunk ht_3 (actual rows=961 loops=1) + Filter: ("timestamp" > 'Mon Dec 30 00:00:00 2019'::timestamp without time zone) +(19 rows) + +--generate the results into two different files +\set ECHO errors +--- Unoptimized results ++++ Optimized results +@@ -1,6 +1,6 @@ + setting | value + ----------------------------------+------- +- timescaledb.enable_optimizations | off ++ timescaledb.enable_optimizations | on + timescaledb.enable_chunk_append | on + (2 rows) + +--- Unoptimized results ++++ Optimized results +@@ -1,7 +1,7 @@ + setting | value + ----------------------------------+------- +- timescaledb.enable_optimizations | off +- timescaledb.enable_chunk_append | on ++ timescaledb.enable_optimizations | on ++ timescaledb.enable_chunk_append | off + (2 rows) + + time | temp | colorid diff --git a/test/expected/chunk_adaptive-13.out b/test/expected/chunk_adaptive-13.out new file mode 100644 index 000000000..8c0fcdbdf --- /dev/null +++ b/test/expected/chunk_adaptive-13.out @@ -0,0 +1,766 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +-- Valid chunk sizing function for testing +CREATE OR REPLACE FUNCTION calculate_chunk_interval( + dimension_id INTEGER, + dimension_coord BIGINT, + chunk_target_size BIGINT +) + RETURNS BIGINT LANGUAGE PLPGSQL AS +$BODY$ +DECLARE +BEGIN + RETURN -1; +END +$BODY$; +-- Chunk sizing function with bad signature +CREATE OR REPLACE FUNCTION bad_calculate_chunk_interval( + dimension_id INTEGER +) + RETURNS BIGINT LANGUAGE PLPGSQL AS +$BODY$ +DECLARE +BEGIN + RETURN -1; +END +$BODY$; +-- Set a fixed memory cache size to make tests determinstic +-- (independent of available machine memory) +SELECT * FROM test.set_memory_cache_size('2GB'); + set_memory_cache_size +----------------------- + 2147483648 +(1 row) + +-- test NULL handling +\set ON_ERROR_STOP 0 +SELECT * FROM set_adaptive_chunking(NULL,NULL); +ERROR: invalid hypertable: cannot be NULL +\set ON_ERROR_STOP 1 +CREATE TABLE test_adaptive(time timestamptz, temp float, location int); +\set ON_ERROR_STOP 0 +-- Bad signature of sizing func should fail +SELECT create_hypertable('test_adaptive', 'time', + chunk_target_size => '1MB', + chunk_sizing_func => 'bad_calculate_chunk_interval'); +ERROR: invalid function signature +\set ON_ERROR_STOP 1 +-- Setting sizing func with correct signature should work +SELECT create_hypertable('test_adaptive', 'time', + chunk_target_size => '1MB', + chunk_sizing_func => 'calculate_chunk_interval'); +WARNING: target chunk size for adaptive chunking is less than 10 MB +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (1,public,test_adaptive,t) +(1 row) + +DROP TABLE test_adaptive; +CREATE TABLE test_adaptive(time timestamptz, temp float, location int); +-- Size but no explicit func should use default func +SELECT create_hypertable('test_adaptive', 'time', + chunk_target_size => '1MB', + create_default_indexes => true); +WARNING: target chunk size for adaptive chunking is less than 10 MB +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (2,public,test_adaptive,t) +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 1048576 +(1 row) + +-- Check that adaptive chunking sets a 1 day default chunk time +-- interval => 86400000000 microseconds +SELECT * FROM _timescaledb_catalog.dimension; + id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func +----+---------------+-------------+--------------------------+---------+------------+--------------------------+-------------------+-----------------+-------------------------+------------------ + 2 | 2 | time | timestamp with time zone | t | | | | 86400000000 | | +(1 row) + +-- Change the target size +SELECT * FROM set_adaptive_chunking('test_adaptive', '2MB'); +WARNING: target chunk size for adaptive chunking is less than 10 MB + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 2097152 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 2097152 +(1 row) + +\set ON_ERROR_STOP 0 +-- Setting NULL func should fail +SELECT * FROM set_adaptive_chunking('test_adaptive', '1MB', NULL); +ERROR: invalid chunk sizing function +\set ON_ERROR_STOP 1 +-- Setting NULL size disables adaptive chunking +SELECT * FROM set_adaptive_chunking('test_adaptive', NULL); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 0 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 0 +(1 row) + +SELECT * FROM set_adaptive_chunking('test_adaptive', '1MB'); +WARNING: target chunk size for adaptive chunking is less than 10 MB + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 1048576 +(1 row) + +-- Setting size to 'off' should also disable +SELECT * FROM set_adaptive_chunking('test_adaptive', 'off'); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 0 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 0 +(1 row) + +-- Setting 0 size should also disable +SELECT * FROM set_adaptive_chunking('test_adaptive', '0MB'); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 0 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 0 +(1 row) + +SELECT * FROM set_adaptive_chunking('test_adaptive', '1MB'); +WARNING: target chunk size for adaptive chunking is less than 10 MB + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 1048576 +(1 row) + +-- No warning about small target size if > 10MB +SELECT * FROM set_adaptive_chunking('test_adaptive', '11MB'); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 11534336 +(1 row) + +-- Setting size to 'estimate' should also estimate size +SELECT * FROM set_adaptive_chunking('test_adaptive', 'estimate'); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 1932735283 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 1932735283 +(1 row) + +-- Use a lower memory setting to test that the calculated chunk_target_size is reduced +SELECT * FROM test.set_memory_cache_size('512MB'); + set_memory_cache_size +----------------------- + 536870912 +(1 row) + +SELECT * FROM set_adaptive_chunking('test_adaptive', 'estimate'); + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 483183820 +(1 row) + +SELECT table_name, chunk_sizing_func_schema, chunk_sizing_func_name, chunk_target_size +FROM _timescaledb_catalog.hypertable; + table_name | chunk_sizing_func_schema | chunk_sizing_func_name | chunk_target_size +---------------+--------------------------+--------------------------+------------------- + test_adaptive | _timescaledb_internal | calculate_chunk_interval | 483183820 +(1 row) + +-- Reset memory settings +SELECT * FROM test.set_memory_cache_size('2GB'); + set_memory_cache_size +----------------------- + 2147483648 +(1 row) + +-- Set a reasonable test value +SELECT * FROM set_adaptive_chunking('test_adaptive', '1MB'); +WARNING: target chunk size for adaptive chunking is less than 10 MB + chunk_sizing_func | chunk_target_size +------------------------------------------------+------------------- + _timescaledb_internal.calculate_chunk_interval | 1048576 +(1 row) + +-- Show the interval length before and after adaptation +SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension; + id | hypertable_id | interval_length +----+---------------+----------------- + 2 | 2 | 86400000000 +(1 row) + +-- Generate data to create chunks. We use the hash of the time value +-- to get determinstic location IDs so that we always spread these +-- values the same way across space partitions +INSERT INTO test_adaptive +SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM +generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days', + '2017-03-07T18:18:03+00'::timestamptz, + '2 minutes') as time; +SELECT chunk_name, primary_dimension, range_start, range_end +FROM timescaledb_information.chunks +WHERE hypertable_name = 'test_adaptive' ORDER BY chunk_name; + chunk_name | primary_dimension | range_start | range_end +-------------------+-------------------+-------------------------------------+------------------------------------- + _hyper_2_10_chunk | time | Fri Sep 23 22:08:15.728855 2016 PDT | Sat Oct 01 13:16:09.024252 2016 PDT + _hyper_2_11_chunk | time | Sat Oct 01 13:16:09.024252 2016 PDT | Fri Oct 14 03:19:44.231212 2016 PDT + _hyper_2_12_chunk | time | Fri Oct 14 03:19:44.231212 2016 PDT | Wed Oct 26 19:20:54.4938 2016 PDT + _hyper_2_13_chunk | time | Wed Oct 26 19:20:54.4938 2016 PDT | Fri Nov 04 04:03:56.248528 2016 PDT + _hyper_2_14_chunk | time | Fri Nov 04 04:03:56.248528 2016 PDT | Fri Nov 18 21:58:20.411232 2016 PST + _hyper_2_15_chunk | time | Fri Nov 18 21:58:20.411232 2016 PST | Sat Dec 03 16:52:44.573936 2016 PST + _hyper_2_16_chunk | time | Sat Dec 03 16:52:44.573936 2016 PST | Sun Dec 18 11:47:08.73664 2016 PST + _hyper_2_17_chunk | time | Sun Dec 18 11:47:08.73664 2016 PST | Mon Jan 02 06:41:32.899344 2017 PST + _hyper_2_18_chunk | time | Mon Jan 02 06:41:32.899344 2017 PST | Tue Jan 17 01:35:57.062048 2017 PST + _hyper_2_19_chunk | time | Tue Jan 17 01:35:57.062048 2017 PST | Tue Jan 31 20:30:21.224752 2017 PST + _hyper_2_1_chunk | time | Mon Sep 12 17:00:00 2016 PDT | Tue Sep 13 17:00:00 2016 PDT + _hyper_2_20_chunk | time | Tue Jan 31 20:30:21.224752 2017 PST | Wed Feb 15 15:24:45.387456 2017 PST + _hyper_2_21_chunk | time | Wed Feb 15 15:24:45.387456 2017 PST | Thu Mar 02 10:19:09.55016 2017 PST + _hyper_2_22_chunk | time | Thu Mar 02 10:19:09.55016 2017 PST | Fri Mar 17 06:13:33.712864 2017 PDT + _hyper_2_2_chunk | time | Tue Sep 13 17:00:00 2016 PDT | Wed Sep 14 17:00:00 2016 PDT + _hyper_2_3_chunk | time | Wed Sep 14 17:00:00 2016 PDT | Thu Sep 15 17:00:00 2016 PDT + _hyper_2_4_chunk | time | Thu Sep 15 17:00:00 2016 PDT | Fri Sep 16 15:02:54.2208 2016 PDT + _hyper_2_5_chunk | time | Fri Sep 16 15:02:54.2208 2016 PDT | Sun Sep 18 03:12:14.342144 2016 PDT + _hyper_2_6_chunk | time | Sun Sep 18 03:12:14.342144 2016 PDT | Mon Sep 19 15:21:34.463488 2016 PDT + _hyper_2_7_chunk | time | Mon Sep 19 15:21:34.463488 2016 PDT | Wed Sep 21 03:30:54.584832 2016 PDT + _hyper_2_8_chunk | time | Wed Sep 21 03:30:54.584832 2016 PDT | Thu Sep 22 03:45:14.901568 2016 PDT + _hyper_2_9_chunk | time | Thu Sep 22 03:45:14.901568 2016 PDT | Fri Sep 23 22:08:15.728855 2016 PDT +(22 rows) + +-- Do same thing without an index on the time column. This affects +-- both the calculation of fill-factor of the chunk and its size +CREATE TABLE test_adaptive_no_index(time timestamptz, temp float, location int); +-- Size but no explicit func should use default func +-- No default indexes should warn and use heap scan for min and max +SELECT create_hypertable('test_adaptive_no_index', 'time', + chunk_target_size => '1MB', + create_default_indexes => false); +WARNING: target chunk size for adaptive chunking is less than 10 MB +WARNING: no index on "time" found for adaptive chunking on hypertable "test_adaptive_no_index" +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------------- + (3,public,test_adaptive_no_index,t) +(1 row) + +SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension; + id | hypertable_id | interval_length +----+---------------+----------------- + 2 | 2 | 1277664162704 + 3 | 3 | 86400000000 +(2 rows) + +INSERT INTO test_adaptive_no_index +SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM +generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days', + '2017-03-07T18:18:03+00'::timestamptz, + '2 minutes') as time; +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_23_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_23_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_24_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_23_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_24_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_25_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_24_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_25_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_26_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_25_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_26_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_27_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_26_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_27_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_28_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_27_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_28_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_29_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_28_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_29_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_30_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_29_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_30_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_31_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_30_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_31_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_32_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_31_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_32_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_33_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_32_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_33_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_34_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_33_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_34_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_35_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_34_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_35_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_36_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_35_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_36_chunk" +WARNING: no index on "time" found for adaptive chunking on chunk "_hyper_3_37_chunk" +SELECT chunk_name, primary_dimension, range_start, range_end +FROM timescaledb_information.chunks +WHERE hypertable_name = 'test_adaptive_no_index' ORDER BY chunk_name; + chunk_name | primary_dimension | range_start | range_end +-------------------+-------------------+-------------------------------------+------------------------------------- + _hyper_3_23_chunk | time | Mon Sep 12 17:00:00 2016 PDT | Tue Sep 13 17:00:00 2016 PDT + _hyper_3_24_chunk | time | Tue Sep 13 17:00:00 2016 PDT | Wed Sep 14 17:00:00 2016 PDT + _hyper_3_25_chunk | time | Wed Sep 14 17:00:00 2016 PDT | Thu Sep 15 17:00:00 2016 PDT + _hyper_3_26_chunk | time | Thu Sep 15 17:00:00 2016 PDT | Sun Sep 18 02:18:45.310968 2016 PDT + _hyper_3_27_chunk | time | Sun Sep 18 02:18:45.310968 2016 PDT | Sun Sep 18 06:20:21.359312 2016 PDT + _hyper_3_28_chunk | time | Sun Sep 18 06:20:21.359312 2016 PDT | Wed Sep 21 08:25:00.957966 2016 PDT + _hyper_3_29_chunk | time | Wed Sep 21 08:25:00.957966 2016 PDT | Thu Sep 22 03:26:42.599807 2016 PDT + _hyper_3_30_chunk | time | Thu Sep 22 03:26:42.599807 2016 PDT | Sun Sep 25 18:03:30.59359 2016 PDT + _hyper_3_31_chunk | time | Sun Sep 25 18:03:30.59359 2016 PDT | Sat Oct 08 05:32:02.75732 2016 PDT + _hyper_3_32_chunk | time | Sat Oct 08 05:32:02.75732 2016 PDT | Mon Oct 31 07:33:42.652938 2016 PDT + _hyper_3_33_chunk | time | Mon Oct 31 07:33:42.652938 2016 PDT | Wed Nov 23 08:35:22.548556 2016 PST + _hyper_3_34_chunk | time | Wed Nov 23 08:35:22.548556 2016 PST | Thu Dec 15 09:48:28.1888 2016 PST + _hyper_3_35_chunk | time | Thu Dec 15 09:48:28.1888 2016 PST | Wed Jan 11 04:57:38.357845 2017 PST + _hyper_3_36_chunk | time | Wed Jan 11 04:57:38.357845 2017 PST | Tue Feb 07 00:06:48.52689 2017 PST + _hyper_3_37_chunk | time | Tue Feb 07 00:06:48.52689 2017 PST | Sun Mar 05 19:15:58.695935 2017 PST + _hyper_3_38_chunk | time | Sun Mar 05 19:15:58.695935 2017 PST | Sat Apr 01 15:25:08.86498 2017 PDT +(16 rows) + +-- Test added to check that the correct index (i.e. time index) is being used +-- to find the min and max. Previously a bug selected the first index listed, +-- which in this case is location rather than time and therefore could return +-- the wrong min and max if items at the start and end of the index did not have +-- the correct min and max timestamps. +-- +-- In this test, we create chunks with a lot of locations with only one reading +-- that is at the beginning of the time frame, and then one location in the middle +-- of the range that has two readings, one that is the same as the others and one +-- that is larger. The algorithm should use these two readings for min & max; however, +-- if it's broken (as it was before), it would choose just the reading that is common +-- to all the locations. +CREATE TABLE test_adaptive_correct_index(time timestamptz, temp float, location int); +SELECT create_hypertable('test_adaptive_correct_index', 'time', + chunk_target_size => '100MB', + chunk_time_interval => 86400000000, + create_default_indexes => false); +WARNING: no index on "time" found for adaptive chunking on hypertable "test_adaptive_correct_index" +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------------------ + (4,public,test_adaptive_correct_index,t) +(1 row) + +CREATE INDEX ON test_adaptive_correct_index(location); +CREATE INDEX ON test_adaptive_correct_index(time DESC); +-- First chunk +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-01T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(1, 1000) as val; +INSERT INTO test_adaptive_correct_index +SELECT time, 0.0, '1500' FROM +generate_series('2018-01-01T00:00:00+00'::timestamptz, + '2018-01-01T20:00:00+00'::timestamptz, + '10 hours') as time; +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-01T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(2001, 3000) as val; +-- Second chunk +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-02T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(1, 1000) as val; +INSERT INTO test_adaptive_correct_index +SELECT time, 0.0, '1500' FROM +generate_series('2018-01-02T00:00:00+00'::timestamptz, + '2018-01-02T20:00:00+00'::timestamptz, + '10 hours') as time; +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-02T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(2001, 3000) as val; +-- Third chunk +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-03T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(1, 1000) as val; +INSERT INTO test_adaptive_correct_index +SELECT time, 0.0, '1500' FROM +generate_series('2018-01-03T00:00:00+00'::timestamptz, + '2018-01-03T20:00:00+00'::timestamptz, + '10 hours') as time; +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-03T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(2001, 3000) as val; +-- This should be the start of the fourth chunk +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-04T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(1, 1000) as val; +INSERT INTO test_adaptive_correct_index +SELECT time, 0.0, '1500' FROM +generate_series('2018-01-04T00:00:00+00'::timestamptz, + '2018-01-04T20:00:00+00'::timestamptz, + '10 hours') as time; +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-04T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(2001, 3000) as val; +-- If working correctly, this goes in the 4th chunk, otherwise its a separate 5th chunk +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-05T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(1, 1000) as val; +INSERT INTO test_adaptive_correct_index +SELECT time, 0.0, '1500' FROM +generate_series('2018-01-05T00:00:00+00'::timestamptz, + '2018-01-05T20:00:00+00'::timestamptz, + '10 hours') as time; +INSERT INTO test_adaptive_correct_index +SELECT '2018-01-05T00:00:00+00'::timestamptz, val, val + 1 FROM +generate_series(2001, 3000) as val; +-- This should show 4 chunks, rather than 5 +SELECT count(*) +FROM timescaledb_information.chunks +WHERE hypertable_name = 'test_adaptive_correct_index'; + count +------- + 4 +(1 row) + +-- The interval_length should no longer be 86400000000 for our hypertable, so 3rd column so be true. +-- Note: the exact interval_length is non-deterministic, so we can't use its actual value for tests +SELECT id, hypertable_id, interval_length > 86400000000 FROM _timescaledb_catalog.dimension; + id | hypertable_id | ?column? +----+---------------+---------- + 2 | 2 | t + 3 | 3 | t + 4 | 4 | t +(3 rows) + +-- Drop because it's size and estimated chunk_interval is non-deterministic so +-- we don't want to make other tests flaky. +DROP TABLE test_adaptive_correct_index; +-- Test with space partitioning. This might affect the estimation +-- since there are more chunks in the same time interval and space +-- chunks might be unevenly filled. +CREATE TABLE test_adaptive_space(time timestamptz, temp float, location int); +SELECT create_hypertable('test_adaptive_space', 'time', 'location', 2, + chunk_target_size => '1MB', + create_default_indexes => true); +WARNING: target chunk size for adaptive chunking is less than 10 MB +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------------- + (5,public,test_adaptive_space,t) +(1 row) + +SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension; + id | hypertable_id | interval_length +----+---------------+----------------- + 2 | 2 | 1277664162704 + 3 | 3 | 2315350169045 + 5 | 5 | 86400000000 + 6 | 5 | +(4 rows) + +INSERT INTO test_adaptive_space +SELECT time, random() * 35, _timescaledb_internal.get_partition_hash(time) FROM +generate_series('2017-03-07T18:18:03+00'::timestamptz - interval '175 days', + '2017-03-07T18:18:03+00'::timestamptz, + '2 minutes') as time; +\x +SELECT chunk_name, range_start, range_end +FROM timescaledb_information.chunks +WHERE hypertable_name = 'test_adaptive_space' ORDER BY chunk_name; +-[ RECORD 1 ]------------------------------------ +chunk_name | _hyper_5_43_chunk +range_start | Mon Sep 12 17:00:00 2016 PDT +range_end | Tue Sep 13 17:00:00 2016 PDT +-[ RECORD 2 ]------------------------------------ +chunk_name | _hyper_5_44_chunk +range_start | Mon Sep 12 17:00:00 2016 PDT +range_end | Tue Sep 13 17:00:00 2016 PDT +-[ RECORD 3 ]------------------------------------ +chunk_name | _hyper_5_45_chunk +range_start | Tue Sep 13 17:00:00 2016 PDT +range_end | Wed Sep 14 17:00:00 2016 PDT +-[ RECORD 4 ]------------------------------------ +chunk_name | _hyper_5_46_chunk +range_start | Tue Sep 13 17:00:00 2016 PDT +range_end | Wed Sep 14 17:00:00 2016 PDT +-[ RECORD 5 ]------------------------------------ +chunk_name | _hyper_5_47_chunk +range_start | Wed Sep 14 17:00:00 2016 PDT +range_end | Thu Sep 15 11:47:51.47376 2016 PDT +-[ RECORD 6 ]------------------------------------ +chunk_name | _hyper_5_48_chunk +range_start | Wed Sep 14 17:00:00 2016 PDT +range_end | Thu Sep 15 11:47:51.47376 2016 PDT +-[ RECORD 7 ]------------------------------------ +chunk_name | _hyper_5_49_chunk +range_start | Thu Sep 15 11:47:51.47376 2016 PDT +range_end | Sat Sep 17 02:40:49.182352 2016 PDT +-[ RECORD 8 ]------------------------------------ +chunk_name | _hyper_5_50_chunk +range_start | Thu Sep 15 11:47:51.47376 2016 PDT +range_end | Sat Sep 17 02:40:49.182352 2016 PDT +-[ RECORD 9 ]------------------------------------ +chunk_name | _hyper_5_51_chunk +range_start | Sat Sep 17 02:40:49.182352 2016 PDT +range_end | Sun Sep 18 17:33:46.890944 2016 PDT +-[ RECORD 10 ]----------------------------------- +chunk_name | _hyper_5_52_chunk +range_start | Sat Sep 17 02:40:49.182352 2016 PDT +range_end | Sun Sep 18 17:33:46.890944 2016 PDT +-[ RECORD 11 ]----------------------------------- +chunk_name | _hyper_5_53_chunk +range_start | Sun Sep 18 17:33:46.890944 2016 PDT +range_end | Sun Sep 18 20:35:55.67676 2016 PDT +-[ RECORD 12 ]----------------------------------- +chunk_name | _hyper_5_54_chunk +range_start | Sun Sep 18 17:33:46.890944 2016 PDT +range_end | Sun Sep 18 20:35:55.67676 2016 PDT +-[ RECORD 13 ]----------------------------------- +chunk_name | _hyper_5_55_chunk +range_start | Sun Sep 18 20:35:55.67676 2016 PDT +range_end | Tue Sep 20 18:46:40.16883 2016 PDT +-[ RECORD 14 ]----------------------------------- +chunk_name | _hyper_5_56_chunk +range_start | Sun Sep 18 20:35:55.67676 2016 PDT +range_end | Tue Sep 20 18:46:40.16883 2016 PDT +-[ RECORD 15 ]----------------------------------- +chunk_name | _hyper_5_57_chunk +range_start | Tue Sep 20 18:46:40.16883 2016 PDT +range_end | Sun Oct 02 16:44:29.071032 2016 PDT +-[ RECORD 16 ]----------------------------------- +chunk_name | _hyper_5_58_chunk +range_start | Tue Sep 20 18:46:40.16883 2016 PDT +range_end | Sun Oct 02 16:44:29.071032 2016 PDT +-[ RECORD 17 ]----------------------------------- +chunk_name | _hyper_5_59_chunk +range_start | Sun Oct 02 16:44:29.071032 2016 PDT +range_end | Tue Oct 11 00:37:03.738979 2016 PDT +-[ RECORD 18 ]----------------------------------- +chunk_name | _hyper_5_60_chunk +range_start | Sun Oct 02 16:44:29.071032 2016 PDT +range_end | Tue Oct 11 00:37:03.738979 2016 PDT +-[ RECORD 19 ]----------------------------------- +chunk_name | _hyper_5_61_chunk +range_start | Tue Oct 11 00:37:03.738979 2016 PDT +range_end | Thu Oct 27 03:05:25.740618 2016 PDT +-[ RECORD 20 ]----------------------------------- +chunk_name | _hyper_5_62_chunk +range_start | Tue Oct 11 00:37:03.738979 2016 PDT +range_end | Thu Oct 27 03:05:25.740618 2016 PDT +-[ RECORD 21 ]----------------------------------- +chunk_name | _hyper_5_63_chunk +range_start | Thu Oct 27 03:05:25.740618 2016 PDT +range_end | Sun Nov 13 12:38:49.541703 2016 PST +-[ RECORD 22 ]----------------------------------- +chunk_name | _hyper_5_64_chunk +range_start | Thu Oct 27 03:05:25.740618 2016 PDT +range_end | Sun Nov 13 12:38:49.541703 2016 PST +-[ RECORD 23 ]----------------------------------- +chunk_name | _hyper_5_65_chunk +range_start | Sun Nov 13 12:38:49.541703 2016 PST +range_end | Fri Dec 02 17:45:40.237036 2016 PST +-[ RECORD 24 ]----------------------------------- +chunk_name | _hyper_5_66_chunk +range_start | Sun Nov 13 12:38:49.541703 2016 PST +range_end | Fri Dec 02 17:45:40.237036 2016 PST +-[ RECORD 25 ]----------------------------------- +chunk_name | _hyper_5_67_chunk +range_start | Fri Dec 02 17:45:40.237036 2016 PST +range_end | Wed Dec 21 22:52:30.932369 2016 PST +-[ RECORD 26 ]----------------------------------- +chunk_name | _hyper_5_68_chunk +range_start | Fri Dec 02 17:45:40.237036 2016 PST +range_end | Wed Dec 21 22:52:30.932369 2016 PST +-[ RECORD 27 ]----------------------------------- +chunk_name | _hyper_5_69_chunk +range_start | Wed Dec 21 22:52:30.932369 2016 PST +range_end | Tue Jan 10 03:59:21.627702 2017 PST +-[ RECORD 28 ]----------------------------------- +chunk_name | _hyper_5_70_chunk +range_start | Wed Dec 21 22:52:30.932369 2016 PST +range_end | Tue Jan 10 03:59:21.627702 2017 PST +-[ RECORD 29 ]----------------------------------- +chunk_name | _hyper_5_71_chunk +range_start | Tue Jan 10 03:59:21.627702 2017 PST +range_end | Sun Jan 29 09:06:12.323035 2017 PST +-[ RECORD 30 ]----------------------------------- +chunk_name | _hyper_5_72_chunk +range_start | Tue Jan 10 03:59:21.627702 2017 PST +range_end | Sun Jan 29 09:06:12.323035 2017 PST +-[ RECORD 31 ]----------------------------------- +chunk_name | _hyper_5_73_chunk +range_start | Sun Jan 29 09:06:12.323035 2017 PST +range_end | Fri Feb 17 14:13:03.018368 2017 PST +-[ RECORD 32 ]----------------------------------- +chunk_name | _hyper_5_74_chunk +range_start | Sun Jan 29 09:06:12.323035 2017 PST +range_end | Fri Feb 17 14:13:03.018368 2017 PST +-[ RECORD 33 ]----------------------------------- +chunk_name | _hyper_5_75_chunk +range_start | Fri Feb 17 14:13:03.018368 2017 PST +range_end | Wed Mar 08 19:19:53.713701 2017 PST +-[ RECORD 34 ]----------------------------------- +chunk_name | _hyper_5_76_chunk +range_start | Fri Feb 17 14:13:03.018368 2017 PST +range_end | Wed Mar 08 19:19:53.713701 2017 PST + +SELECT * +FROM timescaledb_information.dimensions +WHERE hypertable_name = 'test_adaptive_space' ORDER BY dimension_number; +-[ RECORD 1 ]-----+---------------------------------------- +hypertable_schema | public +hypertable_name | test_adaptive_space +dimension_number | 1 +column_name | time +column_type | timestamp with time zone +dimension_type | Time +time_interval | @ 19 days 5 hours 6 mins 50.695333 secs +integer_interval | +integer_now_func | +num_partitions | +-[ RECORD 2 ]-----+---------------------------------------- +hypertable_schema | public +hypertable_name | test_adaptive_space +dimension_number | 2 +column_name | location +column_type | integer +dimension_type | Space +time_interval | +integer_interval | +integer_now_func | +num_partitions | 2 + +\x +SELECT * +FROM chunks_detailed_size('test_adaptive_space') ORDER BY chunk_name; + chunk_schema | chunk_name | table_bytes | index_bytes | toast_bytes | total_bytes | node_name +-----------------------+-------------------+-------------+-------------+-------------+-------------+----------- + _timescaledb_internal | _hyper_5_43_chunk | 8192 | 32768 | 0 | 40960 | + _timescaledb_internal | _hyper_5_44_chunk | 8192 | 32768 | 0 | 40960 | + _timescaledb_internal | _hyper_5_45_chunk | 49152 | 57344 | 0 | 106496 | + _timescaledb_internal | _hyper_5_46_chunk | 49152 | 57344 | 0 | 106496 | + _timescaledb_internal | _hyper_5_47_chunk | 40960 | 49152 | 0 | 90112 | + _timescaledb_internal | _hyper_5_48_chunk | 40960 | 32768 | 0 | 73728 | + _timescaledb_internal | _hyper_5_49_chunk | 57344 | 81920 | 0 | 139264 | + _timescaledb_internal | _hyper_5_50_chunk | 57344 | 81920 | 0 | 139264 | + _timescaledb_internal | _hyper_5_51_chunk | 57344 | 81920 | 0 | 139264 | + _timescaledb_internal | _hyper_5_52_chunk | 57344 | 81920 | 0 | 139264 | + _timescaledb_internal | _hyper_5_53_chunk | 8192 | 32768 | 0 | 40960 | + _timescaledb_internal | _hyper_5_54_chunk | 8192 | 32768 | 0 | 40960 | + _timescaledb_internal | _hyper_5_55_chunk | 65536 | 106496 | 0 | 172032 | + _timescaledb_internal | _hyper_5_56_chunk | 65536 | 98304 | 0 | 163840 | + _timescaledb_internal | _hyper_5_57_chunk | 253952 | 360448 | 0 | 614400 | + _timescaledb_internal | _hyper_5_58_chunk | 253952 | 368640 | 0 | 622592 | + _timescaledb_internal | _hyper_5_59_chunk | 180224 | 303104 | 0 | 483328 | + _timescaledb_internal | _hyper_5_60_chunk | 188416 | 303104 | 0 | 491520 | + _timescaledb_internal | _hyper_5_61_chunk | 327680 | 540672 | 0 | 868352 | + _timescaledb_internal | _hyper_5_62_chunk | 327680 | 532480 | 0 | 860160 | + _timescaledb_internal | _hyper_5_63_chunk | 360448 | 581632 | 0 | 942080 | + _timescaledb_internal | _hyper_5_64_chunk | 352256 | 589824 | 0 | 942080 | + _timescaledb_internal | _hyper_5_65_chunk | 385024 | 598016 | 0 | 983040 | + _timescaledb_internal | _hyper_5_66_chunk | 393216 | 614400 | 0 | 1007616 | + _timescaledb_internal | _hyper_5_67_chunk | 385024 | 598016 | 0 | 983040 | + _timescaledb_internal | _hyper_5_68_chunk | 393216 | 598016 | 0 | 991232 | + _timescaledb_internal | _hyper_5_69_chunk | 393216 | 622592 | 0 | 1015808 | + _timescaledb_internal | _hyper_5_70_chunk | 385024 | 606208 | 0 | 991232 | + _timescaledb_internal | _hyper_5_71_chunk | 385024 | 614400 | 0 | 999424 | + _timescaledb_internal | _hyper_5_72_chunk | 393216 | 622592 | 0 | 1015808 | + _timescaledb_internal | _hyper_5_73_chunk | 393216 | 614400 | 0 | 1007616 | + _timescaledb_internal | _hyper_5_74_chunk | 385024 | 614400 | 0 | 999424 | + _timescaledb_internal | _hyper_5_75_chunk | 360448 | 581632 | 0 | 942080 | + _timescaledb_internal | _hyper_5_76_chunk | 368640 | 598016 | 0 | 966656 | +(34 rows) + +SELECT id, hypertable_id, interval_length FROM _timescaledb_catalog.dimension; + id | hypertable_id | interval_length +----+---------------+----------------- + 2 | 2 | 1277664162704 + 3 | 3 | 2315350169045 + 6 | 5 | + 5 | 5 | 1660010695333 +(4 rows) + +-- A previous version stopped working as soon as hypertable_id stopped being +-- equal to dimension_id (i.e., there was a hypertable with more than 1 dimension). +-- This test comes after test_adaptive_space, which has 2 dimensions, and makes +-- sure that it still works. +CREATE TABLE test_adaptive_after_multiple_dims(time timestamptz, temp float, location int); +SELECT create_hypertable('test_adaptive_after_multiple_dims', 'time', + chunk_target_size => '100MB', + create_default_indexes => true); +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------------------------ + (6,public,test_adaptive_after_multiple_dims,t) +(1 row) + +INSERT INTO test_adaptive_after_multiple_dims VALUES('2018-01-01T00:00:00+00'::timestamptz, 0.0, 5); +\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2 +\set ON_ERROR_STOP 0 +SELECT * FROM set_adaptive_chunking('test_adaptive', '2MB'); +ERROR: must be owner of hypertable "test_adaptive" +\set ON_ERROR_STOP 1 +\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER +-- Now make sure renaming schema gets propagated to the func_schema +DROP TABLE test_adaptive; +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE SCHEMA IF NOT EXISTS my_chunk_func_schema; +CREATE OR REPLACE FUNCTION my_chunk_func_schema.calculate_chunk_interval( + dimension_id INTEGER, + dimension_coord BIGINT, + chunk_target_size BIGINT +) + RETURNS BIGINT LANGUAGE PLPGSQL AS +$BODY$ +DECLARE +BEGIN + RETURN 2; +END +$BODY$; +CREATE TABLE test_adaptive(time timestamptz, temp float, location int); +SELECT create_hypertable('test_adaptive', 'time', + chunk_target_size => '1MB', + chunk_sizing_func => 'my_chunk_func_schema.calculate_chunk_interval'); +WARNING: target chunk size for adaptive chunking is less than 10 MB +NOTICE: adaptive chunking is a BETA feature and is not recommended for production deployments +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (7,public,test_adaptive,t) +(1 row) + +ALTER SCHEMA my_chunk_func_schema RENAME TO new_chunk_func_schema; +INSERT INTO test_adaptive VALUES (now(), 1.0, 1); diff --git a/test/expected/custom_type-13.out b/test/expected/custom_type-13.out new file mode 100644 index 000000000..0c97313fd --- /dev/null +++ b/test/expected/custom_type-13.out @@ -0,0 +1,100 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION customtype_in(cstring) RETURNS customtype AS +'timestamptz_in' +LANGUAGE internal IMMUTABLE STRICT; +NOTICE: type "customtype" is not yet defined +CREATE OR REPLACE FUNCTION customtype_out(customtype) RETURNS cstring AS +'timestamptz_out' +LANGUAGE internal IMMUTABLE STRICT; +NOTICE: argument type customtype is only a shell +CREATE OR REPLACE FUNCTION customtype_recv(internal) RETURNS customtype AS +'timestamptz_recv' +LANGUAGE internal IMMUTABLE STRICT; +NOTICE: return type customtype is only a shell +CREATE OR REPLACE FUNCTION customtype_send(customtype) RETURNS bytea AS +'timestamptz_send' +LANGUAGE internal IMMUTABLE STRICT; +NOTICE: argument type customtype is only a shell +CREATE TYPE customtype ( + INPUT = customtype_in, + OUTPUT = customtype_out, + RECEIVE = customtype_recv, + SEND = customtype_send, + LIKE = TIMESTAMPTZ +); +CREATE CAST (customtype AS bigint) +WITHOUT FUNCTION AS ASSIGNMENT; +CREATE CAST (bigint AS customtype) +WITHOUT FUNCTION AS IMPLICIT; +CREATE CAST (customtype AS timestamptz) +WITHOUT FUNCTION AS ASSIGNMENT; +CREATE CAST (timestamptz AS customtype) +WITHOUT FUNCTION AS ASSIGNMENT; +CREATE OR REPLACE FUNCTION customtype_lt(customtype, customtype) RETURNS bool AS +'timestamp_lt' +LANGUAGE internal IMMUTABLE STRICT; +CREATE OPERATOR < ( + LEFTARG = customtype, + RIGHTARG = customtype, + PROCEDURE = customtype_lt, + COMMUTATOR = >, + NEGATOR = >=, + RESTRICT = scalarltsel, + JOIN = scalarltjoinsel +); +CREATE OR REPLACE FUNCTION customtype_ge(customtype, customtype) RETURNS bool AS +'timestamp_ge' +LANGUAGE internal IMMUTABLE STRICT; +CREATE OPERATOR >= ( + LEFTARG = customtype, + RIGHTARG = customtype, + PROCEDURE = customtype_ge, + COMMUTATOR = <=, + NEGATOR = <, + RESTRICT = scalargtsel, + JOIN = scalargtjoinsel +); +\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER +CREATE TABLE customtype_test(time_custom customtype, val int); +\set ON_ERROR_STOP 0 +-- Using interval type for chunk time interval should fail with custom time type +SELECT create_hypertable('customtype_test', 'time_custom', chunk_time_interval => INTERVAL '1 day', create_default_indexes=>false); +ERROR: invalid interval type for customtype dimension +\set ON_ERROR_STOP 1 +SELECT create_hypertable('customtype_test', 'time_custom', chunk_time_interval => 10e6::bigint, create_default_indexes=>false); +NOTICE: adding not-null constraint to column "time_custom" + create_hypertable +------------------------------ + (1,public,customtype_test,t) +(1 row) + +INSERT INTO customtype_test VALUES ('2001-01-01 01:02:03'::customtype, 10); +INSERT INTO customtype_test VALUES ('2001-01-01 01:02:03'::customtype, 10); +INSERT INTO customtype_test VALUES ('2001-01-01 01:02:03'::customtype, 10); +EXPLAIN (costs off) SELECT * FROM customtype_test; + QUERY PLAN +------------------------------ + Seq Scan on _hyper_1_1_chunk +(1 row) + +INSERT INTO customtype_test VALUES ('2001-01-01 01:02:23'::customtype, 11); +EXPLAIN (costs off) SELECT * FROM customtype_test; + QUERY PLAN +------------------------------------ + Append + -> Seq Scan on _hyper_1_1_chunk + -> Seq Scan on _hyper_1_2_chunk +(3 rows) + +SELECT * FROM customtype_test; + time_custom | val +------------------------------+----- + Mon Jan 01 01:02:03 2001 PST | 10 + Mon Jan 01 01:02:03 2001 PST | 10 + Mon Jan 01 01:02:03 2001 PST | 10 + Mon Jan 01 01:02:23 2001 PST | 11 +(4 rows) + diff --git a/test/expected/insert-13.out b/test/expected/insert-13.out new file mode 100644 index 000000000..f1f46212f --- /dev/null +++ b/test/expected/insert-13.out @@ -0,0 +1,661 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\ir include/insert_two_partitions.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE PUBLIC."two_Partitions" ( + "timeCustom" BIGINT NOT NULL, + device_id TEXT NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL, + series_bool BOOLEAN NULL +); +CREATE INDEX ON PUBLIC."two_Partitions" (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, device_id); +SELECT * FROM create_hypertable('"public"."two_Partitions"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month')); + hypertable_id | schema_name | table_name | created +---------------+-------------+----------------+--------- + 1 | public | two_Partitions | t +(1 row) + +\set QUIET off +BEGIN; +BEGIN +\COPY public."two_Partitions" FROM 'data/ds1_dev1_1.tsv' NULL AS ''; +COPY 7 +COMMIT; +COMMIT +INSERT INTO public."two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES +(1257987600000000000, 'dev1', 1.5, 1), +(1257987600000000000, 'dev1', 1.5, 2), +(1257894000000000000, 'dev2', 1.5, 1), +(1257894002000000000, 'dev1', 2.5, 3); +INSERT 0 4 +INSERT INTO "two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES +(1257894000000000000, 'dev2', 1.5, 2); +INSERT 0 1 +\set QUIET on +SELECT * FROM test.show_columnsp('_timescaledb_internal.%_hyper%'); + Relation | Kind | Column | Column type | NotNull +------------------------------------------------------------------------------------+------+-------------+------------------+--------- + _timescaledb_internal._hyper_1_1_chunk | r | timeCustom | bigint | t + _timescaledb_internal._hyper_1_1_chunk | r | device_id | text | t + _timescaledb_internal._hyper_1_1_chunk | r | series_0 | double precision | f + _timescaledb_internal._hyper_1_1_chunk | r | series_1 | double precision | f + _timescaledb_internal._hyper_1_1_chunk | r | series_2 | double precision | f + _timescaledb_internal._hyper_1_1_chunk | r | series_bool | boolean | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_device_id_timeCustom_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_device_id_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_device_id_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_device_id_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_0_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_0_idx" | i | series_0 | double precision | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" | i | series_1 | double precision | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_2_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_2_idx" | i | series_2 | double precision | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" | i | series_bool | boolean | f + _timescaledb_internal._hyper_1_2_chunk | r | timeCustom | bigint | t + _timescaledb_internal._hyper_1_2_chunk | r | device_id | text | t + _timescaledb_internal._hyper_1_2_chunk | r | series_0 | double precision | f + _timescaledb_internal._hyper_1_2_chunk | r | series_1 | double precision | f + _timescaledb_internal._hyper_1_2_chunk | r | series_2 | double precision | f + _timescaledb_internal._hyper_1_2_chunk | r | series_bool | boolean | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_device_id_timeCustom_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_device_id_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_device_id_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_device_id_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_0_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_0_idx" | i | series_0 | double precision | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" | i | series_1 | double precision | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_2_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_2_idx" | i | series_2 | double precision | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_bool_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_bool_idx" | i | series_bool | boolean | f + _timescaledb_internal._hyper_1_3_chunk | r | timeCustom | bigint | t + _timescaledb_internal._hyper_1_3_chunk | r | device_id | text | t + _timescaledb_internal._hyper_1_3_chunk | r | series_0 | double precision | f + _timescaledb_internal._hyper_1_3_chunk | r | series_1 | double precision | f + _timescaledb_internal._hyper_1_3_chunk | r | series_2 | double precision | f + _timescaledb_internal._hyper_1_3_chunk | r | series_bool | boolean | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_device_id_timeCustom_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_device_id_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_device_id_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_device_id_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_0_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_0_idx" | i | series_0 | double precision | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" | i | series_1 | double precision | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_2_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_2_idx" | i | series_2 | double precision | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_bool_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_bool_idx" | i | series_bool | boolean | f + _timescaledb_internal._hyper_1_4_chunk | r | timeCustom | bigint | t + _timescaledb_internal._hyper_1_4_chunk | r | device_id | text | t + _timescaledb_internal._hyper_1_4_chunk | r | series_0 | double precision | f + _timescaledb_internal._hyper_1_4_chunk | r | series_1 | double precision | f + _timescaledb_internal._hyper_1_4_chunk | r | series_2 | double precision | f + _timescaledb_internal._hyper_1_4_chunk | r | series_bool | boolean | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_device_id_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_device_id_idx" | i | device_id | text | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_0_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_0_idx" | i | series_0 | double precision | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" | i | series_1 | double precision | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_2_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_2_idx" | i | series_2 | double precision | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_bool_idx" | i | timeCustom | bigint | f + _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_bool_idx" | i | series_bool | boolean | f +(76 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+------------------------------------------------------------------------------------+--------------------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_device_id_timeCustom_idx" | {device_id,timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_0_idx" | {timeCustom,series_0} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" | {timeCustom,series_1} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_2_idx" | {timeCustom,series_2} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_series_bool_idx" | {timeCustom,series_bool} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_device_id_idx" | {timeCustom,device_id} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."_hyper_1_1_chunk_two_Partitions_timeCustom_idx" | {timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_device_id_timeCustom_idx" | {device_id,timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_0_idx" | {timeCustom,series_0} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" | {timeCustom,series_1} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_2_idx" | {timeCustom,series_2} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_series_bool_idx" | {timeCustom,series_bool} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_device_id_idx" | {timeCustom,device_id} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."_hyper_1_2_chunk_two_Partitions_timeCustom_idx" | {timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_device_id_timeCustom_idx" | {device_id,timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_0_idx" | {timeCustom,series_0} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" | {timeCustom,series_1} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_2_idx" | {timeCustom,series_2} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_series_bool_idx" | {timeCustom,series_bool} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_device_id_idx" | {timeCustom,device_id} | | f | f | f | + _timescaledb_internal._hyper_1_3_chunk | _timescaledb_internal."_hyper_1_3_chunk_two_Partitions_timeCustom_idx" | {timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" | {device_id,timeCustom} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_0_idx" | {timeCustom,series_0} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" | {timeCustom,series_1} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_2_idx" | {timeCustom,series_2} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_series_bool_idx" | {timeCustom,series_bool} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_device_id_idx" | {timeCustom,device_id} | | f | f | f | + _timescaledb_internal._hyper_1_4_chunk | _timescaledb_internal."_hyper_1_4_chunk_two_Partitions_timeCustom_idx" | {timeCustom} | | f | f | f | +(28 rows) + +SELECT * FROM _timescaledb_catalog.chunk; + id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped +----+---------------+-----------------------+------------------+---------------------+--------- + 1 | 1 | _timescaledb_internal | _hyper_1_1_chunk | | f + 2 | 1 | _timescaledb_internal | _hyper_1_2_chunk | | f + 3 | 1 | _timescaledb_internal | _hyper_1_3_chunk | | f + 4 | 1 | _timescaledb_internal | _hyper_1_4_chunk | | f +(4 rows) + +SELECT * FROM "two_Partitions" ORDER BY "timeCustom", device_id, series_0, series_1; + timeCustom | device_id | series_0 | series_1 | series_2 | series_bool +---------------------+-----------+----------+----------+----------+------------- + 1257894000000000000 | dev1 | 1.5 | 1 | 2 | t + 1257894000000000000 | dev1 | 1.5 | 2 | | + 1257894000000000000 | dev2 | 1.5 | 1 | | + 1257894000000000000 | dev2 | 1.5 | 2 | | + 1257894000000001000 | dev1 | 2.5 | 3 | | + 1257894001000000000 | dev1 | 3.5 | 4 | | + 1257894002000000000 | dev1 | 2.5 | 3 | | + 1257894002000000000 | dev1 | 5.5 | 6 | | t + 1257894002000000000 | dev1 | 5.5 | 7 | | f + 1257897600000000000 | dev1 | 4.5 | 5 | | f + 1257987600000000000 | dev1 | 1.5 | 1 | | + 1257987600000000000 | dev1 | 1.5 | 2 | | +(12 rows) + +SELECT * FROM ONLY "two_Partitions"; + timeCustom | device_id | series_0 | series_1 | series_2 | series_bool +------------+-----------+----------+----------+----------+------------- +(0 rows) + +CREATE TABLE error_test(time timestamp, temp float8, device text NOT NULL); +SELECT create_hypertable('error_test', 'time', 'device', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------- + (2,public,error_test,t) +(1 row) + +\set QUIET off +INSERT INTO error_test VALUES ('Mon Mar 20 09:18:20.1 2017', 21.3, 'dev1'); +INSERT 0 1 +\set ON_ERROR_STOP 0 +-- generate insert error +INSERT INTO error_test VALUES ('Mon Mar 20 09:18:22.3 2017', 21.1, NULL); +ERROR: null value in column "device" of relation "_hyper_2_6_chunk" violates not-null constraint +\set ON_ERROR_STOP 1 +INSERT INTO error_test VALUES ('Mon Mar 20 09:18:25.7 2017', 22.4, 'dev2'); +INSERT 0 1 +\set QUIET on +SELECT * FROM error_test; + time | temp | device +----------------------------+------+-------- + Mon Mar 20 09:18:20.1 2017 | 21.3 | dev1 + Mon Mar 20 09:18:25.7 2017 | 22.4 | dev2 +(2 rows) + +--test character(9) partition keys since there were issues with padding causing partitioning errors +CREATE TABLE tick_character ( + symbol character(9) NOT NULL, + mid REAL NOT NULL, + spread REAL NOT NULL, + time TIMESTAMPTZ NOT NULL +); +SELECT create_hypertable ('tick_character', 'time', 'symbol', 2); + create_hypertable +----------------------------- + (3,public,tick_character,t) +(1 row) + +INSERT INTO tick_character ( symbol, mid, spread, time ) VALUES ( 'GBPJPY', 142.639000, 5.80, 'Mon Mar 20 09:18:22.3 2017') RETURNING time, symbol, mid; + time | symbol | mid +--------------------------------+-----------+--------- + Mon Mar 20 09:18:22.3 2017 PDT | GBPJPY | 142.639 +(1 row) + +SELECT * FROM tick_character; + symbol | mid | spread | time +-----------+---------+--------+-------------------------------- + GBPJPY | 142.639 | 5.8 | Mon Mar 20 09:18:22.3 2017 PDT +(1 row) + +CREATE TABLE date_col_test(time date, temp float8, device text NOT NULL); +SELECT create_hypertable('date_col_test', 'time', 'device', 1000, chunk_time_interval => INTERVAL '1 Day'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (4,public,date_col_test,t) +(1 row) + +INSERT INTO date_col_test +VALUES ('2001-02-01', 98, 'dev1'), +('2001-03-02', 98, 'dev1'); +SELECT * FROM date_col_test WHERE time > '2001-01-01'; + time | temp | device +------------+------+-------- + 03-02-2001 | 98 | dev1 + 02-01-2001 | 98 | dev1 +(2 rows) + +-- Out-of-order insertion regression test. +-- this used to trip an assert in subspace_store.c checking that +-- max_open_chunks_per_insert was obeyed +set timescaledb.max_open_chunks_per_insert=1; +CREATE TABLE chunk_assert_fail(i bigint, j bigint); +SELECT create_hypertable('chunk_assert_fail', 'i', 'j', 1000, chunk_time_interval=>1); +NOTICE: adding not-null constraint to column "i" + create_hypertable +-------------------------------- + (5,public,chunk_assert_fail,t) +(1 row) + +insert into chunk_assert_fail values (1, 1), (1, 2), (2,1); +select * from chunk_assert_fail; + i | j +---+--- + 1 | 1 + 1 | 2 + 2 | 1 +(3 rows) + +CREATE TABLE one_space_test(time timestamp, temp float8, device text NOT NULL); +SELECT create_hypertable('one_space_test', 'time', 'device', 1); +NOTICE: adding not-null constraint to column "time" + create_hypertable +----------------------------- + (6,public,one_space_test,t) +(1 row) + +INSERT INTO one_space_test VALUES +('2001-01-01 01:01:01', 1.0, 'device'), +('2002-01-01 01:02:01', 1.0, 'device'); +SELECT * FROM one_space_test; + time | temp | device +--------------------------+------+-------- + Mon Jan 01 01:01:01 2001 | 1 | device + Tue Jan 01 01:02:01 2002 | 1 | device +(2 rows) + +--CTE & EXPLAIN ANALYZE TESTS +WITH insert_cte as ( + INSERT INTO one_space_test VALUES + ('2001-01-01 01:02:01', 1.0, 'device') + RETURNING *) +SELECT * FROM insert_cte; + time | temp | device +--------------------------+------+-------- + Mon Jan 01 01:02:01 2001 | 1 | device +(1 row) + +EXPLAIN (analyze, costs off, timing off) --can't turn summary off in 9.6 so instead grep it away at end. +WITH insert_cte as ( + INSERT INTO one_space_test VALUES + ('2001-01-01 01:03:01', 1.0, 'device') + ) +SELECT 1 \g | grep -v "Planning" | grep -v "Execution" + QUERY PLAN +------------------------------------------------------------------------- + Result (actual rows=1 loops=1) + CTE insert_cte + -> Custom Scan (HypertableInsert) (never executed) + -> Insert on one_space_test (actual rows=0 loops=1) + -> Custom Scan (ChunkDispatch) (actual rows=1 loops=1) + -> Result (actual rows=1 loops=1) +(8 rows) + +-- INSERTs can exclude chunks based on constraints +EXPLAIN (costs off) INSERT INTO chunk_assert_fail SELECT i, j FROM chunk_assert_fail; + QUERY PLAN +------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on chunk_assert_fail + -> Custom Scan (ChunkDispatch) + -> Append + -> Seq Scan on _hyper_5_11_chunk + -> Seq Scan on _hyper_5_12_chunk + -> Seq Scan on _hyper_5_13_chunk +(7 rows) + +EXPLAIN (costs off) INSERT INTO chunk_assert_fail SELECT i, j FROM chunk_assert_fail WHERE i < 1; + QUERY PLAN +-------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on chunk_assert_fail + -> Custom Scan (ChunkDispatch) + -> Result + One-Time Filter: false +(5 rows) + +EXPLAIN (costs off) INSERT INTO chunk_assert_fail SELECT i, j FROM chunk_assert_fail WHERE i = 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on chunk_assert_fail + -> Custom Scan (ChunkDispatch) + -> Append + -> Index Scan using _hyper_5_12_chunk_chunk_assert_fail_i_idx on _hyper_5_12_chunk + Index Cond: (i = 1) + -> Index Scan using _hyper_5_11_chunk_chunk_assert_fail_i_idx on _hyper_5_11_chunk + Index Cond: (i = 1) +(8 rows) + +EXPLAIN (costs off) INSERT INTO chunk_assert_fail SELECT i, j FROM chunk_assert_fail WHERE i > 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on chunk_assert_fail + -> Custom Scan (ChunkDispatch) + -> Index Scan using _hyper_5_13_chunk_chunk_assert_fail_i_idx on _hyper_5_13_chunk + Index Cond: (i > 1) +(5 rows) + +INSERT INTO chunk_assert_fail SELECT i, j FROM chunk_assert_fail WHERE i > 1; +EXPLAIN (costs off) INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time < 'infinity' LIMIT 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on one_space_test + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Scan using _hyper_6_14_chunk_one_space_test_time_idx on _hyper_6_14_chunk + Index Cond: ("time" < 'infinity'::timestamp without time zone) + -> Index Scan using _hyper_6_15_chunk_one_space_test_time_idx on _hyper_6_15_chunk + Index Cond: ("time" < 'infinity'::timestamp without time zone) +(9 rows) + +EXPLAIN (costs off) INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time >= 'infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on one_space_test + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time <= '-infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on one_space_test + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time > '-infinity' LIMIT 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on one_space_test + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Scan using _hyper_6_14_chunk_one_space_test_time_idx on _hyper_6_14_chunk + Index Cond: ("time" > '-infinity'::timestamp without time zone) + -> Index Scan using _hyper_6_15_chunk_one_space_test_time_idx on _hyper_6_15_chunk + Index Cond: ("time" > '-infinity'::timestamp without time zone) +(9 rows) + +INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time < 'infinity' LIMIT 1; +INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time >= 'infinity' LIMIT 1; +INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time <= '-infinity' LIMIT 1; +INSERT INTO one_space_test SELECT * FROM one_space_test WHERE time > '-infinity' LIMIT 1; +CREATE TABLE timestamp_inf(time TIMESTAMP); +SELECT create_hypertable('timestamp_inf', 'time'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (7,public,timestamp_inf,t) +(1 row) + +INSERT INTO timestamp_inf VALUES ('2018/01/02'), ('2019/01/02'); +EXPLAIN (costs off) INSERT INTO timestamp_inf SELECT * FROM timestamp_inf + WHERE time < 'infinity' LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on timestamp_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Only Scan using _hyper_7_17_chunk_timestamp_inf_time_idx on _hyper_7_17_chunk + Index Cond: ("time" < 'infinity'::timestamp without time zone) + -> Index Only Scan using _hyper_7_16_chunk_timestamp_inf_time_idx on _hyper_7_16_chunk + Index Cond: ("time" < 'infinity'::timestamp without time zone) +(9 rows) + +EXPLAIN (costs off) INSERT INTO timestamp_inf SELECT * FROM timestamp_inf + WHERE time >= 'infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on timestamp_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO timestamp_inf SELECT * FROM timestamp_inf + WHERE time <= '-infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on timestamp_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO timestamp_inf SELECT * FROM timestamp_inf + WHERE time > '-infinity' LIMIT 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on timestamp_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Only Scan using _hyper_7_17_chunk_timestamp_inf_time_idx on _hyper_7_17_chunk + Index Cond: ("time" > '-infinity'::timestamp without time zone) + -> Index Only Scan using _hyper_7_16_chunk_timestamp_inf_time_idx on _hyper_7_16_chunk + Index Cond: ("time" > '-infinity'::timestamp without time zone) +(9 rows) + +CREATE TABLE date_inf(time DATE); +SELECT create_hypertable('date_inf', 'time'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +----------------------- + (8,public,date_inf,t) +(1 row) + +INSERT INTO date_inf VALUES ('2018/01/02'), ('2019/01/02'); +EXPLAIN (costs off) INSERT INTO date_inf SELECT * FROM date_inf + WHERE time < 'infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on date_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Only Scan using _hyper_8_18_chunk_date_inf_time_idx on _hyper_8_18_chunk + Index Cond: ("time" < 'infinity'::date) + -> Index Only Scan using _hyper_8_19_chunk_date_inf_time_idx on _hyper_8_19_chunk + Index Cond: ("time" < 'infinity'::date) +(9 rows) + +EXPLAIN (costs off) INSERT INTO date_inf SELECT * FROM date_inf + WHERE time >= 'infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on date_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO date_inf SELECT * FROM date_inf + WHERE time <= '-infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on date_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Result + One-Time Filter: false +(6 rows) + +EXPLAIN (costs off) INSERT INTO date_inf SELECT * FROM date_inf + WHERE time > '-infinity' LIMIT 1; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------- + Custom Scan (HypertableInsert) + -> Insert on date_inf + -> Custom Scan (ChunkDispatch) + -> Limit + -> Append + -> Index Only Scan using _hyper_8_18_chunk_date_inf_time_idx on _hyper_8_18_chunk + Index Cond: ("time" > '-infinity'::date) + -> Index Only Scan using _hyper_8_19_chunk_date_inf_time_idx on _hyper_8_19_chunk + Index Cond: ("time" > '-infinity'::date) +(9 rows) + +-- test INSERT with cached plans / plpgsql functions +-- https://github.com/timescale/timescaledb/issues/1809 +CREATE TABLE status_table(a int, b int, last_ts timestamptz, UNIQUE(a,b)); +CREATE TABLE metrics(time timestamptz NOT NULL, value float); +CREATE TABLE metrics2(time timestamptz NOT NULL, value float); +SELECT (create_hypertable(t,'time')).table_name FROM (VALUES ('metrics'),('metrics2')) v(t); + table_name +------------ + metrics + metrics2 +(2 rows) + +INSERT INTO metrics VALUES ('2000-01-01',random()), ('2000-02-01',random()), ('2000-03-01',random()); +CREATE OR REPLACE FUNCTION insert_test() RETURNS VOID LANGUAGE plpgsql AS +$$ + DECLARE + r RECORD; + BEGIN + FOR r IN + SELECT * FROM metrics + LOOP + WITH foo AS ( + INSERT INTO metrics2 SELECT * FROM metrics RETURNING * + ) + INSERT INTO status_table (a,b, last_ts) + VALUES (1,1, now()) + ON CONFLICT (a,b) DO UPDATE SET last_ts=(SELECT max(time) FROM metrics); + END LOOP; + END; +$$; +SELECT insert_test(), insert_test(), insert_test(); + insert_test | insert_test | insert_test +-------------+-------------+------------- + | | +(1 row) + +-- test Postgres crashes on INSERT ... SELECT ... WHERE NOT EXISTS with empty table +-- https://github.com/timescale/timescaledb/issues/1883 +CREATE TABLE readings ( + toe TIMESTAMPTZ NOT NULL, + sensor_id INT NOT NULL, + value INT NOT NULL +); +SELECT create_hypertable( + 'readings', + 'toe', + chunk_time_interval => interval '1 day', + if_not_exists => TRUE, + migrate_data => TRUE +); + create_hypertable +------------------------ + (11,public,readings,t) +(1 row) + +EXPLAIN (costs off) +INSERT INTO readings +SELECT '2020-05-09 10:34:35.296288+00', 1, 0 +WHERE NOT EXISTS ( + SELECT 1 + FROM readings + WHERE sensor_id = 1 + AND toe = '2020-05-09 10:34:35.296288+00' +); + QUERY PLAN +----------------------------------------------------- + Custom Scan (HypertableInsert) + InitPlan 1 (returns $0) + -> Result + One-Time Filter: false + -> Insert on readings + -> Result + One-Time Filter: (NOT $0) + -> Custom Scan (ChunkDispatch) + -> Result + One-Time Filter: (NOT $0) +(10 rows) + +INSERT INTO readings +SELECT '2020-05-09 10:34:35.296288+00', 1, 0 +WHERE NOT EXISTS ( + SELECT 1 + FROM readings + WHERE sensor_id = 1 + AND toe = '2020-05-09 10:34:35.296288+00' +); +DROP TABLE readings; +CREATE TABLE sample_table ( + sequence INTEGER NOT NULL, + time TIMESTAMP WITHOUT TIME ZONE NOT NULL, + value NUMERIC NOT NULL, + UNIQUE (sequence, time) +); +SELECT * FROM create_hypertable('sample_table', 'time', + chunk_time_interval => INTERVAL '1 day'); + hypertable_id | schema_name | table_name | created +---------------+-------------+--------------+--------- + 12 | public | sample_table | t +(1 row) + +INSERT INTO sample_table (sequence,time,value) VALUES + (7, generate_series(TIMESTAMP '2019-08-01', TIMESTAMP '2019-08-10', INTERVAL '10 minutes'), ROUND(RANDOM()*10)::int); +\set ON_ERROR_STOP 0 +INSERT INTO sample_table (sequence,time,value) VALUES + (7, generate_series(TIMESTAMP '2019-07-21', TIMESTAMP '2019-08-01', INTERVAL '10 minutes'), ROUND(RANDOM()*10)::int); +ERROR: duplicate key value violates unique constraint "27_1_sample_table_sequence_time_key" +\set ON_ERROR_STOP 1 +INSERT INTO sample_table (sequence,time,value) VALUES + (7,generate_series(TIMESTAMP '2019-01-01', TIMESTAMP '2019-07-01', '10 minutes'), ROUND(RANDOM()*10)::int); +DROP TABLE sample_table; diff --git a/test/expected/multi_transaction_index-13.out b/test/expected/multi_transaction_index-13.out new file mode 100644 index 000000000..8b281dc73 --- /dev/null +++ b/test/expected/multi_transaction_index-13.out @@ -0,0 +1,404 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE index_test(id serial, time timestamptz, device integer, temp float); +SELECT * FROM test.show_columns('index_test'); + Column | Type | NotNull +--------+--------------------------+--------- + id | integer | t + time | timestamp with time zone | f + device | integer | f + temp | double precision | f +(4 rows) + +-- Test that we can handle difference in attnos across hypertable and +-- chunks by dropping the ID column +ALTER TABLE index_test DROP COLUMN id; +SELECT * FROM test.show_columns('index_test'); + Column | Type | NotNull +--------+--------------------------+--------- + time | timestamp with time zone | f + device | integer | f + temp | double precision | f +(3 rows) + +-- No pre-existing UNIQUE index, so partitioning on two columns should work +SELECT create_hypertable('index_test', 'time', 'device', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------- + (1,public,index_test,t) +(1 row) + +INSERT INTO index_test VALUES ('2017-01-20T09:00:01', 1, 17.5); +\set ON_ERROR_STOP 0 +-- cannot create a UNIQUE index with transaction_per_chunk +CREATE UNIQUE INDEX index_test_time_device_idx ON index_test (time) WITH (timescaledb.transaction_per_chunk); +ERROR: cannot use timescaledb.transaction_per_chunk with UNIQUE or PRIMARY KEY +CREATE UNIQUE INDEX index_test_time_device_idx ON index_test (time, device) WITH(timescaledb.transaction_per_chunk); +ERROR: cannot use timescaledb.transaction_per_chunk with UNIQUE or PRIMARY KEY +\set ON_ERROR_STOP 1 +CREATE INDEX index_test_time_device_idx ON index_test (time, device) WITH (timescaledb.transaction_per_chunk); +-- Regular index need not cover all partitioning columns +CREATE INDEX ON index_test (time, temp) WITH (timescaledb.transaction_per_chunk); +-- Create another chunk +INSERT INTO index_test VALUES ('2017-04-20T09:00:01', 1, 17.5); +-- New index should have been recursed to chunks +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_device_idx | {time,device} | | f | f | f | + index_test_time_idx | {time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk') ORDER BY 1,2; + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_idx | {time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_device_idx | {time,device} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_idx | {time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_device_idx | {time,device} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | +(8 rows) + +SELECT * FROM _timescaledb_catalog.chunk_index ORDER BY index_name; + chunk_id | index_name | hypertable_id | hypertable_index_name +----------+---------------------------------------------+---------------+---------------------------- + 1 | _hyper_1_1_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 1 | _hyper_1_1_chunk_index_test_time_device_idx | 1 | index_test_time_device_idx + 1 | _hyper_1_1_chunk_index_test_time_idx | 1 | index_test_time_idx + 1 | _hyper_1_1_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx + 2 | _hyper_1_2_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 2 | _hyper_1_2_chunk_index_test_time_device_idx | 1 | index_test_time_device_idx + 2 | _hyper_1_2_chunk_index_test_time_idx | 1 | index_test_time_idx + 2 | _hyper_1_2_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx +(8 rows) + +ALTER INDEX index_test_time_idx RENAME TO index_test_time_idx2; +-- Metadata and index should have changed name +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_device_idx | {time,device} | | f | f | f | + index_test_time_idx2 | {time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk') ORDER BY 1,2; + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_idx2 | {time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_device_idx | {time,device} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_idx2 | {time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_device_idx | {time,device} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | +(8 rows) + +SELECT * FROM _timescaledb_catalog.chunk_index ORDER BY index_name; + chunk_id | index_name | hypertable_id | hypertable_index_name +----------+---------------------------------------------+---------------+---------------------------- + 1 | _hyper_1_1_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 1 | _hyper_1_1_chunk_index_test_time_device_idx | 1 | index_test_time_device_idx + 1 | _hyper_1_1_chunk_index_test_time_idx2 | 1 | index_test_time_idx2 + 1 | _hyper_1_1_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx + 2 | _hyper_1_2_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 2 | _hyper_1_2_chunk_index_test_time_device_idx | 1 | index_test_time_device_idx + 2 | _hyper_1_2_chunk_index_test_time_idx2 | 1 | index_test_time_idx2 + 2 | _hyper_1_2_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx +(8 rows) + +DROP INDEX index_test_time_idx2; +DROP INDEX index_test_time_device_idx; +-- Index should have been dropped +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(2 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +SELECT * FROM _timescaledb_catalog.chunk_index; + chunk_id | index_name | hypertable_id | hypertable_index_name +----------+---------------------------------------------+---------------+---------------------------- + 1 | _hyper_1_1_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 1 | _hyper_1_1_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx + 2 | _hyper_1_2_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 2 | _hyper_1_2_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx +(4 rows) + +-- Create index with long name to see how this is handled on chunks +CREATE INDEX a_hypertable_index_with_a_very_very_long_name_that_truncates ON index_test (time, temp) WITH (timescaledb.transaction_per_chunk); +CREATE INDEX a_hypertable_index_with_a_very_very_long_name_that_truncates_2 ON index_test (time, temp) WITH (timescaledb.transaction_per_chunk); +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + a_hypertable_index_with_a_very_very_long_name_that_truncates | {time,temp} | | f | f | f | + a_hypertable_index_with_a_very_very_long_name_that_truncates_2 | {time,temp} | | f | f | f | + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+---------------------------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_a_hypertable_index_with_a_very_very_long_name_ | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_a_hypertable_index_with_a_very_very_long_nam_1 | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_a_hypertable_index_with_a_very_very_long_name_ | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_a_hypertable_index_with_a_very_very_long_nam_1 | {time,temp} | | f | f | f | +(8 rows) + +DROP INDEX a_hypertable_index_with_a_very_very_long_name_that_truncates; +DROP INDEX a_hypertable_index_with_a_very_very_long_name_that_truncates_2; +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(2 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(2 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | +(4 rows) + +-- Add constraint index +ALTER TABLE index_test ADD UNIQUE (time, device); +SELECT * FROM test.show_indexes('index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------+---------------+------+--------+---------+-----------+------------ + index_test_device_time_idx | {device,time} | | f | f | f | + index_test_time_device_key | {time,device} | | t | f | f | + index_test_time_temp_idx | {time,temp} | | f | f | f | +(3 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+-------------------------------------------------------------------+---------------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal."1_1_index_test_time_device_key" | {time,device} | | t | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_device_time_idx | {device,time} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_index_test_time_temp_idx | {time,temp} | | f | f | f | + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal."2_2_index_test_time_device_key" | {time,device} | | t | f | f | +(6 rows) + +-- Constraint indexes are added to chunk_index table. +SELECT * FROM _timescaledb_catalog.chunk_index; + chunk_id | index_name | hypertable_id | hypertable_index_name +----------+---------------------------------------------+---------------+---------------------------- + 1 | _hyper_1_1_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 1 | _hyper_1_1_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx + 2 | _hyper_1_2_chunk_index_test_device_time_idx | 1 | index_test_device_time_idx + 2 | _hyper_1_2_chunk_index_test_time_temp_idx | 1 | index_test_time_temp_idx + 1 | 1_1_index_test_time_device_key | 1 | index_test_time_device_key + 2 | 2_2_index_test_time_device_key | 1 | index_test_time_device_key +(6 rows) + +SELECT * FROM _timescaledb_catalog.chunk_constraint; + chunk_id | dimension_slice_id | constraint_name | hypertable_constraint_name +----------+--------------------+--------------------------------+---------------------------- + 1 | 1 | constraint_1 | + 1 | 2 | constraint_2 | + 2 | 3 | constraint_3 | + 2 | 2 | constraint_2 | + 1 | | 1_1_index_test_time_device_key | index_test_time_device_key + 2 | | 2_2_index_test_time_device_key | index_test_time_device_key +(6 rows) + +DROP TABLE index_test; +-- Metadata removed +SELECT * FROM _timescaledb_catalog.chunk_index; + chunk_id | index_name | hypertable_id | hypertable_index_name +----------+------------+---------------+----------------------- +(0 rows) + +-- Test that indexes are planned correctly +CREATE TABLE index_expr_test(id serial, time timestamptz, temp float, meta int); +select create_hypertable('index_expr_test', 'time'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------ + (2,public,index_expr_test,t) +(1 row) + +-- Screw up the attribute numbers +ALTER TABLE index_expr_test DROP COLUMN id; +CREATE INDEX ON index_expr_test (meta) WITH (timescaledb.transaction_per_chunk); +INSERT INTO index_expr_test VALUES ('2017-01-20T09:00:01', 17.5, 1); +INSERT INTO index_expr_test VALUES ('2017-01-20T09:00:01', 17.5, 2); +SET enable_seqscan TO false; +SET enable_bitmapscan TO false; +EXPLAIN (verbose, costs off) +SELECT * FROM index_expr_test WHERE meta = 1; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Index Scan using _hyper_2_3_chunk_index_expr_test_meta_idx on _timescaledb_internal._hyper_2_3_chunk + Output: _hyper_2_3_chunk."time", _hyper_2_3_chunk.temp, _hyper_2_3_chunk.meta + Index Cond: (_hyper_2_3_chunk.meta = 1) +(3 rows) + +SELECT * FROM index_expr_test WHERE meta = 1; + time | temp | meta +------------------------------+------+------ + Fri Jan 20 09:00:01 2017 PST | 17.5 | 1 +(1 row) + +SET enable_seqscan TO default; +SET enable_bitmapscan TO default; +\set ON_ERROR_STOP 0 +-- cannot create a transaction_per_chunk index within a transaction block +BEGIN; +CREATE INDEX ON index_expr_test (temp) WITH (timescaledb.transaction_per_chunk); +ERROR: CREATE INDEX ... WITH (timescaledb.transaction_per_chunk) cannot run inside a transaction block +ROLLBACK; +\set ON_ERROR_STOP 1 +DROP TABLE index_expr_test CASCADE; +CREATE TABLE partial_index_test(time INTEGER); +SELECT create_hypertable('partial_index_test', 'time', chunk_time_interval => 1, create_default_indexes => false); +NOTICE: adding not-null constraint to column "time" + create_hypertable +--------------------------------- + (3,public,partial_index_test,t) +(1 row) + +-- create 3 chunks +INSERT INTO partial_index_test(time) SELECT generate_series(0, 2); +select * from partial_index_test order by 1; + time +------ + 0 + 1 + 2 +(3 rows) + +-- create indexes on only 1 of the chunks +CREATE INDEX ON partial_index_test (time) WITH (timescaledb.transaction_per_chunk, timescaledb.max_chunks='1'); +SELECT * FROM test.show_indexes('partial_index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +-----------------------------+---------+------+--------+---------+-----------+------------ + partial_index_test_time_idx | {time} | | f | f | f | +(1 row) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +----------------------------------------+--------------------------------------------------------------------+---------+------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_3_4_chunk | _timescaledb_internal._hyper_3_4_chunk_partial_index_test_time_idx | {time} | | f | f | f | +(1 row) + +-- regerssion test for bug fixed by PR #1008. +-- this caused an assertion failure when a MergeAppend node contained unsorted children +SET enable_seqscan TO false; +SET enable_bitmapscan TO false; +EXPLAIN (verbose, costs off) SELECT * FROM partial_index_test WHERE time < 2 ORDER BY time LIMIT 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Limit + Output: partial_index_test."time" + -> Custom Scan (ChunkAppend) on public.partial_index_test + Output: partial_index_test."time" + Order: partial_index_test."time" + Startup Exclusion: false + Runtime Exclusion: false + -> Index Only Scan using _hyper_3_4_chunk_partial_index_test_time_idx on _timescaledb_internal._hyper_3_4_chunk + Output: _hyper_3_4_chunk."time" + Index Cond: (_hyper_3_4_chunk."time" < 2) + -> Sort + Output: _hyper_3_5_chunk."time" + Sort Key: _hyper_3_5_chunk."time" + -> Seq Scan on _timescaledb_internal._hyper_3_5_chunk + Output: _hyper_3_5_chunk."time" + Filter: (_hyper_3_5_chunk."time" < 2) +(16 rows) + +SELECT * FROM partial_index_test WHERE time < 2 ORDER BY time LIMIT 2; + time +------ + 0 + 1 +(2 rows) + +-- we can drop the partially created index +DROP INDEX partial_index_test_time_idx; +SELECT * FROM test.show_indexes('partial_index_test'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +-------+---------+------+--------+---------+-----------+------------ +(0 rows) + +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +-------+-------+---------+------+--------+---------+-----------+------------ +(0 rows) + +EXPLAIN (verbose, costs off) SELECT * FROM partial_index_test WHERE time < 2 ORDER BY time LIMIT 2; + QUERY PLAN +---------------------------------------------------------------------- + Limit + Output: _hyper_3_4_chunk."time" + -> Sort + Output: _hyper_3_4_chunk."time" + Sort Key: _hyper_3_4_chunk."time" + -> Append + -> Seq Scan on _timescaledb_internal._hyper_3_4_chunk + Output: _hyper_3_4_chunk."time" + Filter: (_hyper_3_4_chunk."time" < 2) + -> Seq Scan on _timescaledb_internal._hyper_3_5_chunk + Output: _hyper_3_5_chunk."time" + Filter: (_hyper_3_5_chunk."time" < 2) +(12 rows) + +SELECT * FROM partial_index_test WHERE time < 2 ORDER BY time LIMIT 2; + time +------ + 0 + 1 +(2 rows) + +SET enable_seqscan TO true; +SET enable_bitmapscan TO true; +\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER_2 +\set ON_ERROR_STOP 0 +CREATE INDEX ON partial_index_test (time) WITH (timescaledb.transaction_per_chunk, timescaledb.max_chunks='1'); +ERROR: must be owner of hypertable "partial_index_test" +\set ON_ERROR_STOP 1 diff --git a/test/expected/parallel-13.out b/test/expected/parallel-13.out new file mode 100644 index 000000000..aa0149451 --- /dev/null +++ b/test/expected/parallel-13.out @@ -0,0 +1,445 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +--parallel queries require big-ish tables so collect them all here +--so that we need to generate queries only once. +-- output with analyze is not stable because it depends on worker assignment +\set PREFIX 'EXPLAIN (costs off)' +\set CHUNK1 _timescaledb_internal._hyper_1_1_chunk +\set CHUNK2 _timescaledb_internal._hyper_1_2_chunk +CREATE TABLE test (i int, j double precision, ts timestamp); +SELECT create_hypertable('test','i',chunk_time_interval:=500000); +NOTICE: adding not-null constraint to column "i" + create_hypertable +------------------- + (1,public,test,t) +(1 row) + +INSERT INTO test SELECT x, x+0.1, _timescaledb_internal.to_timestamp(x*1000) FROM generate_series(0,1000000-1,10) AS x; +ANALYZE test; +ALTER TABLE :CHUNK1 SET (parallel_workers=2); +ALTER TABLE :CHUNK2 SET (parallel_workers=2); +SET work_mem TO '50MB'; +SET force_parallel_mode = 'on'; +SET max_parallel_workers_per_gather = 4; +SET parallel_setup_cost TO 0; +EXPLAIN (costs off) SELECT first(i, j) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT first(i, j) FROM "test"; + first +------- + 0 +(1 row) + +EXPLAIN (costs off) SELECT last(i, j) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT last(i, j) FROM "test"; + last +-------- + 999990 +(1 row) + +EXPLAIN (costs off) SELECT time_bucket('1 second', ts) sec, last(i, j) +FROM "test" +GROUP BY sec +ORDER BY sec +LIMIT 5; + QUERY PLAN +-------------------------------------------------------------------------------------- + Gather + Workers Planned: 1 + Single Copy: true + -> Limit + -> Sort + Sort Key: (time_bucket('@ 1 sec'::interval, _hyper_1_1_chunk.ts)) + -> HashAggregate + Group Key: time_bucket('@ 1 sec'::interval, _hyper_1_1_chunk.ts) + -> Result + -> Append + -> Seq Scan on _hyper_1_1_chunk + -> Seq Scan on _hyper_1_2_chunk +(12 rows) + +-- test single copy parallel plan with parallel chunk append +:PREFIX SELECT time_bucket('1 second', ts) sec, last(i, j) +FROM "test" +WHERE length(version()) > 0 +GROUP BY sec +ORDER BY sec +LIMIT 5; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather + Workers Planned: 1 + Single Copy: true + -> Limit + -> Sort + Sort Key: (time_bucket('@ 1 sec'::interval, test.ts)) + -> HashAggregate + Group Key: time_bucket('@ 1 sec'::interval, test.ts) + -> Result + One-Time Filter: (length(version()) > 0) + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Seq Scan on _hyper_1_1_chunk + -> Result + One-Time Filter: (length(version()) > 0) + -> Seq Scan on _hyper_1_2_chunk +(18 rows) + +SELECT time_bucket('1 second', ts) sec, last(i, j) +FROM "test" +GROUP BY sec +ORDER BY sec +LIMIT 5; + sec | last +--------------------------+------ + Wed Dec 31 16:00:00 1969 | 990 + Wed Dec 31 16:00:01 1969 | 1990 + Wed Dec 31 16:00:02 1969 | 2990 + Wed Dec 31 16:00:03 1969 | 3990 + Wed Dec 31 16:00:04 1969 | 4990 +(5 rows) + +--test variants of histogram +EXPLAIN (costs off) SELECT histogram(i, 1, 1000000, 2) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT histogram(i, 1, 1000000, 2) FROM "test"; + histogram +------------------- + {1,50000,49999,0} +(1 row) + +EXPLAIN (costs off) SELECT histogram(i, 1,1000001,10) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT histogram(i, 1, 1000001, 10) FROM "test"; + histogram +------------------------------------------------------------------ + {1,10000,10000,10000,10000,10000,10000,10000,10000,10000,9999,0} +(1 row) + +EXPLAIN (costs off) SELECT histogram(i, 0,100000,5) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT histogram(i, 0, 100000, 5) FROM "test"; + histogram +------------------------------------ + {0,2000,2000,2000,2000,2000,90000} +(1 row) + +EXPLAIN (costs off) SELECT histogram(i, 10,100000,5) FROM "test"; + QUERY PLAN +--------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Parallel Seq Scan on _hyper_1_2_chunk +(7 rows) + +SELECT histogram(i, 10, 100000, 5) FROM "test"; + histogram +------------------------------------ + {1,2000,2000,2000,2000,1999,90000} +(1 row) + +EXPLAIN (costs off) SELECT histogram(NULL, 10,100000,5) FROM "test" WHERE i = coalesce(-1,j); + QUERY PLAN +------------------------------------------------------------------------------------ + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Parallel Append + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: ((i)::double precision = '-1'::double precision) + -> Parallel Seq Scan on _hyper_1_2_chunk + Filter: ((i)::double precision = '-1'::double precision) +(9 rows) + +SELECT histogram(NULL, 10,100000,5) FROM "test" WHERE i = coalesce(-1,j); + histogram +----------- + +(1 row) + +-- test parallel ChunkAppend +:PREFIX SELECT i FROM "test" WHERE length(version()) > 0; + QUERY PLAN +-------------------------------------------------------------- + Gather + Workers Planned: 1 + Single Copy: true + -> Result + One-Time Filter: (length(version()) > 0) + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Seq Scan on _hyper_1_1_chunk + -> Result + One-Time Filter: (length(version()) > 0) + -> Seq Scan on _hyper_1_2_chunk +(13 rows) + +-- test worker assignment +-- first chunk should have 1 worker and second chunk should have 2 +SET max_parallel_workers_per_gather TO 2; +:PREFIX SELECT count(*) FROM "test" WHERE i >= 400000 AND length(version()) > 0; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Index Only Scan using _hyper_1_1_chunk_test_i_idx on _hyper_1_1_chunk + Index Cond: (i >= 400000) + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_2_chunk + Filter: (i >= 400000) +(16 rows) + +SELECT count(*) FROM "test" WHERE i >= 400000 AND length(version()) > 0; + count +------- + 60000 +(1 row) + +-- test worker assignment +-- first chunk should have 2 worker and second chunk should have 1 +:PREFIX SELECT count(*) FROM "test" WHERE i < 600000 AND length(version()) > 0; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Index Only Scan using _hyper_1_2_chunk_test_i_idx on _hyper_1_2_chunk + Index Cond: (i < 600000) + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (i < 600000) +(16 rows) + +SELECT count(*) FROM "test" WHERE i < 600000 AND length(version()) > 0; + count +------- + 60000 +(1 row) + +-- test ChunkAppend with # workers < # childs +SET max_parallel_workers_per_gather TO 1; +:PREFIX SELECT count(*) FROM "test" WHERE length(version()) > 0; + QUERY PLAN +--------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 1 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_1_chunk + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_2_chunk +(14 rows) + +SELECT count(*) FROM "test" WHERE length(version()) > 0; + count +-------- + 100000 +(1 row) + +-- test ChunkAppend with # workers > # childs +SET max_parallel_workers_per_gather TO 2; +:PREFIX SELECT count(*) FROM "test" WHERE i >= 500000 AND length(version()) > 0; + QUERY PLAN +--------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_2_chunk + Filter: (i >= 500000) +(12 rows) + +SELECT count(*) FROM "test" WHERE i >= 500000 AND length(version()) > 0; + count +------- + 50000 +(1 row) + +RESET max_parallel_workers_per_gather; +-- test partial and non-partial plans +-- these will not be parallel on PG < 11 +ALTER TABLE :CHUNK1 SET (parallel_workers=0); +ALTER TABLE :CHUNK2 SET (parallel_workers=2); +:PREFIX SELECT count(*) FROM "test" WHERE i > 400000 AND length(version()) > 0; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Index Only Scan using _hyper_1_1_chunk_test_i_idx on _hyper_1_1_chunk + Index Cond: (i > 400000) + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_2_chunk + Filter: (i > 400000) +(16 rows) + +ALTER TABLE :CHUNK1 SET (parallel_workers=2); +ALTER TABLE :CHUNK2 SET (parallel_workers=0); +:PREFIX SELECT count(*) FROM "test" WHERE i < 600000 AND length(version()) > 0; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Finalize Aggregate + -> Gather + Workers Planned: 2 + -> Partial Aggregate + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Result + One-Time Filter: (length(version()) > 0) + -> Index Only Scan using _hyper_1_2_chunk_test_i_idx on _hyper_1_2_chunk + Index Cond: (i < 600000) + -> Result + One-Time Filter: (length(version()) > 0) + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (i < 600000) +(16 rows) + +ALTER TABLE :CHUNK1 RESET (parallel_workers); +ALTER TABLE :CHUNK2 RESET (parallel_workers); +-- now() is not marked parallel safe in PostgreSQL < 12 so using now() +-- in a query will prevent parallelism but CURRENT_TIMESTAMP and +-- transaction_timestamp() are marked parallel safe +:PREFIX SELECT i FROM "test" WHERE ts < CURRENT_TIMESTAMP; + QUERY PLAN +------------------------------------------------ + Gather + Workers Planned: 1 + Single Copy: true + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (ts < CURRENT_TIMESTAMP) + -> Seq Scan on _hyper_1_2_chunk + Filter: (ts < CURRENT_TIMESTAMP) +(9 rows) + +:PREFIX SELECT i FROM "test" WHERE ts < transaction_timestamp(); + QUERY PLAN +------------------------------------------------------ + Gather + Workers Planned: 1 + Single Copy: true + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (ts < transaction_timestamp()) + -> Seq Scan on _hyper_1_2_chunk + Filter: (ts < transaction_timestamp()) +(9 rows) + +-- this won't be parallel query because now() is parallel restricted in PG < 12 +:PREFIX SELECT i FROM "test" WHERE ts < now(); + QUERY PLAN +------------------------------------------- + Gather + Workers Planned: 1 + Single Copy: true + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (ts < now()) + -> Seq Scan on _hyper_1_2_chunk + Filter: (ts < now()) +(9 rows) + diff --git a/test/expected/partition-13.out b/test/expected/partition-13.out new file mode 100644 index 000000000..c28ceea1a --- /dev/null +++ b/test/expected/partition-13.out @@ -0,0 +1,521 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE part_legacy(time timestamptz, temp float, device int); +SELECT create_hypertable('part_legacy', 'time', 'device', 2, partitioning_func => '_timescaledb_internal.get_partition_for_key'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------------- + (1,public,part_legacy,t) +(1 row) + +-- Show legacy partitioning function is used +SELECT * FROM _timescaledb_catalog.dimension; + id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func +----+---------------+-------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+-------------------------+------------------ + 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | + 2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_for_key | | | +(2 rows) + +INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 1); +INSERT INTO part_legacy VALUES ('2017-03-22T09:18:23', 23.4, 76); +VACUUM part_legacy; +-- Show two chunks and CHECK constraint with cast +SELECT * FROM test.show_constraintsp('_timescaledb_internal._hyper_1_%_chunk'); + Table | Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated +----------------------------------------+--------------+------+----------+-------+------------------------------------------------------------------------------------------------------------------------------------------------+------------+----------+----------- + _timescaledb_internal._hyper_1_1_chunk | constraint_1 | c | {time} | - | (("time" >= 'Wed Mar 15 17:00:00 2017 PDT'::timestamp with time zone) AND ("time" < 'Wed Mar 22 17:00:00 2017 PDT'::timestamp with time zone)) | f | f | t + _timescaledb_internal._hyper_1_1_chunk | constraint_2 | c | {device} | - | (_timescaledb_internal.get_partition_for_key(device) >= 1073741823) | f | f | t + _timescaledb_internal._hyper_1_2_chunk | constraint_1 | c | {time} | - | (("time" >= 'Wed Mar 15 17:00:00 2017 PDT'::timestamp with time zone) AND ("time" < 'Wed Mar 22 17:00:00 2017 PDT'::timestamp with time zone)) | f | f | t + _timescaledb_internal._hyper_1_2_chunk | constraint_3 | c | {device} | - | (_timescaledb_internal.get_partition_for_key(device) < 1073741823) | f | f | t +(4 rows) + +-- Make sure constraint exclusion works on device column +BEGIN; +-- For plan stability between versions +SET LOCAL enable_bitmapscan = false; +SET LOCAL enable_indexscan = false; +EXPLAIN (verbose, costs off) +SELECT * FROM part_legacy WHERE device = 1; + QUERY PLAN +----------------------------------------------------------------------------------- + Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.temp, _hyper_1_1_chunk.device + Filter: (_hyper_1_1_chunk.device = 1) +(3 rows) + +COMMIT; +CREATE TABLE part_new(time timestamptz, temp float, device int); +SELECT create_hypertable('part_new', 'time', 'device', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +----------------------- + (2,public,part_new,t) +(1 row) + +SELECT * FROM _timescaledb_catalog.dimension; + id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func +----+---------------+-------------+--------------------------+---------+------------+--------------------------+-----------------------+-----------------+-------------------------+------------------ + 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | + 2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_for_key | | | + 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | + 4 | 2 | device | integer | f | 2 | _timescaledb_internal | get_partition_hash | | | +(4 rows) + +INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 1); +INSERT INTO part_new VALUES ('2017-03-22T09:18:23', 23.4, 2); +VACUUM part_new; +-- Show two chunks and CHECK constraint without cast +SELECT * FROM test.show_constraintsp('_timescaledb_internal._hyper_2_%_chunk'); + Table | Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated +----------------------------------------+--------------+------+----------+-------+------------------------------------------------------------------------------------------------------------------------------------------------+------------+----------+----------- + _timescaledb_internal._hyper_2_3_chunk | constraint_4 | c | {time} | - | (("time" >= 'Wed Mar 15 17:00:00 2017 PDT'::timestamp with time zone) AND ("time" < 'Wed Mar 22 17:00:00 2017 PDT'::timestamp with time zone)) | f | f | t + _timescaledb_internal._hyper_2_3_chunk | constraint_5 | c | {device} | - | (_timescaledb_internal.get_partition_hash(device) < 1073741823) | f | f | t + _timescaledb_internal._hyper_2_4_chunk | constraint_4 | c | {time} | - | (("time" >= 'Wed Mar 15 17:00:00 2017 PDT'::timestamp with time zone) AND ("time" < 'Wed Mar 22 17:00:00 2017 PDT'::timestamp with time zone)) | f | f | t + _timescaledb_internal._hyper_2_4_chunk | constraint_6 | c | {device} | - | (_timescaledb_internal.get_partition_hash(device) >= 1073741823) | f | f | t +(4 rows) + +-- Make sure constraint exclusion works on device column +BEGIN; +-- For plan stability between versions +SET LOCAL enable_bitmapscan = false; +SET LOCAL enable_indexscan = false; +EXPLAIN (verbose, costs off) +SELECT * FROM part_new WHERE device = 1; + QUERY PLAN +----------------------------------------------------------------------------------- + Seq Scan on _timescaledb_internal._hyper_2_3_chunk + Output: _hyper_2_3_chunk."time", _hyper_2_3_chunk.temp, _hyper_2_3_chunk.device + Filter: (_hyper_2_3_chunk.device = 1) +(3 rows) + +COMMIT; +CREATE TABLE part_new_convert1(time timestamptz, temp float8, device int); +SELECT create_hypertable('part_new_convert1', 'time', 'temp', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------------------- + (3,public,part_new_convert1,t) +(1 row) + +INSERT INTO part_new_convert1 VALUES ('2017-03-22T09:18:23', 1.0, 2); +\set ON_ERROR_STOP 0 +-- Changing the type of a hash-partitioned column should not be supported +ALTER TABLE part_new_convert1 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 part_new_convert1 ALTER COLUMN time TYPE timestamp; +SELECT * FROM test.show_columnsp('_timescaledb_internal._hyper_3_%_chunk'); + Relation | Kind | Column | Column type | NotNull +----------------------------------------+------+--------+-----------------------------+--------- + _timescaledb_internal._hyper_3_5_chunk | r | time | timestamp without time zone | t + _timescaledb_internal._hyper_3_5_chunk | r | temp | double precision | f + _timescaledb_internal._hyper_3_5_chunk | r | device | integer | f +(3 rows) + +CREATE TABLE part_add_dim(time timestamptz, temp float8, device int, location int); +SELECT create_hypertable('part_add_dim', 'time', 'temp', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +--------------------------- + (4,public,part_add_dim,t) +(1 row) + +\set ON_ERROR_STOP 0 +SELECT add_dimension('part_add_dim', 'location', 2, partitioning_func => 'bad_func'); +ERROR: function "bad_func" does not exist at character 74 +\set ON_ERROR_STOP 1 +SELECT add_dimension('part_add_dim', 'location', 2, partitioning_func => '_timescaledb_internal.get_partition_for_key'); + add_dimension +------------------------------------ + (9,public,part_add_dim,location,t) +(1 row) + +SELECT * FROM _timescaledb_catalog.dimension; + id | hypertable_id | column_name | column_type | aligned | num_slices | partitioning_func_schema | partitioning_func | interval_length | integer_now_func_schema | integer_now_func +----+---------------+-------------+-----------------------------+---------+------------+--------------------------+-----------------------+-----------------+-------------------------+------------------ + 1 | 1 | time | timestamp with time zone | t | | | | 604800000000 | | + 2 | 1 | device | integer | f | 2 | _timescaledb_internal | get_partition_for_key | | | + 3 | 2 | time | timestamp with time zone | t | | | | 604800000000 | | + 4 | 2 | device | integer | f | 2 | _timescaledb_internal | get_partition_hash | | | + 6 | 3 | temp | double precision | f | 2 | _timescaledb_internal | get_partition_hash | | | + 5 | 3 | time | timestamp without time zone | t | | | | 604800000000 | | + 7 | 4 | time | timestamp with time zone | t | | | | 604800000000 | | + 8 | 4 | temp | double precision | f | 2 | _timescaledb_internal | get_partition_hash | | | + 9 | 4 | location | integer | f | 2 | _timescaledb_internal | get_partition_for_key | | | +(9 rows) + +-- Test that we support custom SQL-based partitioning functions and +-- that our native partitioning function handles function expressions +-- as argument +CREATE OR REPLACE FUNCTION custom_partfunc(source anyelement) + RETURNS INTEGER LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +DECLARE + retval INTEGER; +BEGIN + retval = _timescaledb_internal.get_partition_hash(substring(source::text FROM '[A-za-z0-9 ]+')); + RAISE NOTICE 'hash value for % is %', source, retval; + RETURN retval; +END +$BODY$; +CREATE TABLE part_custom_func(time timestamptz, temp float8, device text); +SELECT create_hypertable('part_custom_func', 'time', 'device', 2, partitioning_func => 'custom_partfunc'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------- + (5,public,part_custom_func,t) +(1 row) + +SELECT _timescaledb_internal.get_partition_hash(substring('dev1' FROM '[A-za-z0-9 ]+')); + get_partition_hash +-------------------- + 1129986420 +(1 row) + +SELECT _timescaledb_internal.get_partition_hash('dev1'::text); + get_partition_hash +-------------------- + 1129986420 +(1 row) + +SELECT _timescaledb_internal.get_partition_hash('dev7'::text); + get_partition_hash +-------------------- + 449729092 +(1 row) + +INSERT INTO part_custom_func VALUES ('2017-03-22T09:18:23', 23.4, 'dev1'), + ('2017-03-22T09:18:23', 23.4, 'dev7'); +NOTICE: hash value for dev1 is 1129986420 +NOTICE: hash value for dev1 is 1129986420 +NOTICE: hash value for dev7 is 449729092 +NOTICE: hash value for dev7 is 449729092 +SELECT * FROM test.show_subtables('part_custom_func'); + Child | Tablespace +----------------------------------------+------------ + _timescaledb_internal._hyper_5_6_chunk | + _timescaledb_internal._hyper_5_7_chunk | +(2 rows) + +-- This first test is slightly trivial, but segfaulted in old versions +CREATE TYPE simpl AS (val1 int4); +CREATE OR REPLACE FUNCTION simpl_type_hash(ANYELEMENT) RETURNS int4 AS $$ + SELECT $1.val1; +$$ LANGUAGE SQL IMMUTABLE; +CREATE TABLE simpl_partition ("timestamp" TIMESTAMPTZ, object simpl); +SELECT create_hypertable( + 'simpl_partition', + 'timestamp', + 'object', + 1000, + chunk_time_interval => interval '1 day', + partitioning_func=>'simpl_type_hash'); +NOTICE: adding not-null constraint to column "timestamp" + create_hypertable +------------------------------ + (6,public,simpl_partition,t) +(1 row) + +INSERT INTO simpl_partition VALUES ('2017-03-22T09:18:23', ROW(1)::simpl); +SELECT * from simpl_partition; + timestamp | object +------------------------------+-------- + Wed Mar 22 09:18:23 2017 PDT | (1) +(1 row) + +-- Also test that the fix works when we have more chunks than allowed at once +SET timescaledb.max_open_chunks_per_insert=1; +INSERT INTO simpl_partition VALUES + ('2017-03-22T10:18:23', ROW(0)::simpl), + ('2017-03-22T10:18:23', ROW(1)::simpl), + ('2017-03-22T10:18:23', ROW(2)::simpl), + ('2017-03-22T10:18:23', ROW(3)::simpl), + ('2017-03-22T10:18:23', ROW(4)::simpl), + ('2017-03-22T10:18:23', ROW(5)::simpl); +SET timescaledb.max_open_chunks_per_insert=default; +SELECT * from simpl_partition; + timestamp | object +------------------------------+-------- + Wed Mar 22 09:18:23 2017 PDT | (1) + Wed Mar 22 10:18:23 2017 PDT | (0) + Wed Mar 22 10:18:23 2017 PDT | (1) + Wed Mar 22 10:18:23 2017 PDT | (2) + Wed Mar 22 10:18:23 2017 PDT | (3) + Wed Mar 22 10:18:23 2017 PDT | (4) + Wed Mar 22 10:18:23 2017 PDT | (5) +(7 rows) + +-- Test that index creation is handled correctly. +CREATE TABLE hyper_with_index(time timestamptz, temp float, device int); +CREATE UNIQUE INDEX temp_index ON hyper_with_index(temp); +\set ON_ERROR_STOP 0 +SELECT create_hypertable('hyper_with_index', 'time'); +NOTICE: adding not-null constraint to column "time" +ERROR: cannot create a unique index without the column "time" (used in partitioning) +SELECT create_hypertable('hyper_with_index', 'time', 'device', 2); +NOTICE: adding not-null constraint to column "time" +ERROR: cannot create a unique index without the column "time" (used in partitioning) +SELECT create_hypertable('hyper_with_index', 'time', 'temp', 2); +NOTICE: adding not-null constraint to column "time" +ERROR: cannot create a unique index without the column "time" (used in partitioning) +\set ON_ERROR_STOP 1 +DROP INDEX temp_index; +CREATE UNIQUE INDEX time_index ON hyper_with_index(time); +\set ON_ERROR_STOP 0 +-- should error because device not in index +SELECT create_hypertable('hyper_with_index', 'time', 'device', 4); +NOTICE: adding not-null constraint to column "time" +ERROR: cannot create a unique index without the column "device" (used in partitioning) +\set ON_ERROR_STOP 1 +SELECT create_hypertable('hyper_with_index', 'time'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------------------- + (11,public,hyper_with_index,t) +(1 row) + +-- make sure user created index is used. +-- not using \d or \d+ because output syntax differs +-- between postgres 9 and postgres 10. +SELECT indexname FROM pg_indexes WHERE tablename = 'hyper_with_index'; + indexname +------------ + time_index +(1 row) + +\set ON_ERROR_STOP 0 +SELECT add_dimension('hyper_with_index', 'device', 4); +ERROR: cannot create a unique index without the column "device" (used in partitioning) +\set ON_ERROR_STOP 1 +DROP INDEX time_index; +CREATE UNIQUE INDEX time_space_index ON hyper_with_index(time, device); +SELECT add_dimension('hyper_with_index', 'device', 4); + add_dimension +--------------------------------------- + (23,public,hyper_with_index,device,t) +(1 row) + +CREATE TABLE hyper_with_primary(time TIMESTAMPTZ PRIMARY KEY, temp float, device int); +\set ON_ERROR_STOP 0 +SELECT create_hypertable('hyper_with_primary', 'time', 'device', 4); +ERROR: cannot create a unique index without the column "device" (used in partitioning) +\set ON_ERROR_STOP 1 +SELECT create_hypertable('hyper_with_primary', 'time'); + create_hypertable +---------------------------------- + (13,public,hyper_with_primary,t) +(1 row) + +\set ON_ERROR_STOP 0 +SELECT add_dimension('hyper_with_primary', 'device', 4); +ERROR: cannot create a unique index without the column "device" (used in partitioning) +\set ON_ERROR_STOP 1 +-- NON-unique indexes can still be created +CREATE INDEX temp_index ON hyper_with_index(temp); +-- Make sure custom composite types are supported as dimensions +CREATE TYPE TUPLE as (val1 int4, val2 int4); +CREATE FUNCTION tuple_hash(value ANYELEMENT) RETURNS INT4 +LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +BEGIN + RAISE NOTICE 'custom hash value is: %', value.val1+value.val2; + RETURN value.val1+value.val2; +END +$BODY$; +CREATE TABLE part_custom_dim (time TIMESTAMPTZ, combo TUPLE, device TEXT); +\set ON_ERROR_STOP 0 +-- should fail because no partitioning function supplied and the given custom type +-- has no default hash function +SELECT create_hypertable('part_custom_dim', 'time', 'combo', 4); +NOTICE: adding not-null constraint to column "time" +ERROR: could not find hash function for type tuple +\set ON_ERROR_STOP 1 +SELECT create_hypertable('part_custom_dim', 'time', 'combo', 4, partitioning_func=>'tuple_hash'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------- + (15,public,part_custom_dim,t) +(1 row) + +INSERT INTO part_custom_dim(time, combo) VALUES (now(), (1,2)); +NOTICE: custom hash value is: 3 +NOTICE: custom hash value is: 3 +DROP TABLE part_custom_dim; +-- Now make sure that renaming partitioning_func_schema will get updated properly +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE SCHEMA IF NOT EXISTS my_partitioning_schema; +CREATE FUNCTION my_partitioning_schema.tuple_hash(value ANYELEMENT) RETURNS INT4 +LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +BEGIN + RAISE NOTICE 'custom hash value is: %', value.val1+value.val2; + RETURN value.val1+value.val2; +END +$BODY$; +CREATE TABLE part_custom_dim (time TIMESTAMPTZ, combo TUPLE, device TEXT); +SELECT create_hypertable('part_custom_dim', 'time', 'combo', 4, partitioning_func=>'my_partitioning_schema.tuple_hash'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------- + (16,public,part_custom_dim,t) +(1 row) + +INSERT INTO part_custom_dim(time, combo) VALUES (now(), (1,2)); +NOTICE: custom hash value is: 3 +NOTICE: custom hash value is: 3 +ALTER SCHEMA my_partitioning_schema RENAME TO new_partitioning_schema; +-- Inserts should work even after we rename the schema +INSERT INTO part_custom_dim(time, combo) VALUES (now(), (3,4)); +NOTICE: custom hash value is: 7 +NOTICE: custom hash value is: 7 +-- Test partitioning function on an open (time) dimension +CREATE OR REPLACE FUNCTION time_partfunc(unixtime float8) + RETURNS TIMESTAMPTZ LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +DECLARE + retval TIMESTAMPTZ; +BEGIN + + retval := to_timestamp(unixtime); + RAISE NOTICE 'time value for % is %', unixtime, timezone('UTC', retval); + RETURN retval; +END +$BODY$; +CREATE OR REPLACE FUNCTION time_partfunc_bad_parameters(unixtime float8, extra text) + RETURNS TIMESTAMPTZ LANGUAGE SQL IMMUTABLE AS +$BODY$ + SELECT to_timestamp(unixtime); +$BODY$; +CREATE OR REPLACE FUNCTION time_partfunc_bad_return_type(unixtime float8) + RETURNS FLOAT8 LANGUAGE SQL IMMUTABLE AS +$BODY$ + SELECT unixtime; +$BODY$; +CREATE TABLE part_time_func(time float8, temp float8, device text); +\set ON_ERROR_STOP 0 +-- Should fail due to invalid time column +SELECT create_hypertable('part_time_func', 'time'); +ERROR: invalid type for dimension "time" +-- Should fail due to bad signature of time partitioning function +SELECT create_hypertable('part_time_func', 'time', time_partitioning_func => 'time_partfunc_bad_parameters'); +ERROR: invalid partitioning function +SELECT create_hypertable('part_time_func', 'time', time_partitioning_func => 'time_partfunc_bad_return_type'); +ERROR: invalid partitioning function +\set ON_ERROR_STOP 1 +-- Should work with time partitioning function that returns a valid time type +SELECT create_hypertable('part_time_func', 'time', time_partitioning_func => 'time_partfunc'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +------------------------------ + (17,public,part_time_func,t) +(1 row) + +INSERT INTO part_time_func VALUES (1530214157.134, 23.4, 'dev1'), + (1533214157.8734, 22.3, 'dev7'); +NOTICE: time value for 1530214157.134 is Thu Jun 28 19:29:17.134 2018 +NOTICE: time value for 1530214157.134 is Thu Jun 28 19:29:17.134 2018 +NOTICE: time value for 1530214157.134 is Thu Jun 28 19:29:17.134 2018 +NOTICE: time value for 1530214157.134 is Thu Jun 28 19:29:17.134 2018 +NOTICE: time value for 1533214157.8734 is Thu Aug 02 12:49:17.8734 2018 +NOTICE: time value for 1533214157.8734 is Thu Aug 02 12:49:17.8734 2018 +NOTICE: time value for 1533214157.8734 is Thu Aug 02 12:49:17.8734 2018 +NOTICE: time value for 1533214157.8734 is Thu Aug 02 12:49:17.8734 2018 +SELECT time, temp, device FROM part_time_func; + time | temp | device +-----------------+------+-------- + 1530214157.134 | 23.4 | dev1 + 1533214157.8734 | 22.3 | dev7 +(2 rows) + +SELECT time_partfunc(time) at time zone 'UTC', temp, device FROM part_time_func; +NOTICE: time value for 1530214157.134 is Thu Jun 28 19:29:17.134 2018 +NOTICE: time value for 1533214157.8734 is Thu Aug 02 12:49:17.8734 2018 + timezone | temp | device +-------------------------------+------+-------- + Thu Jun 28 19:29:17.134 2018 | 23.4 | dev1 + Thu Aug 02 12:49:17.8734 2018 | 22.3 | dev7 +(2 rows) + +SELECT * FROM test.show_subtables('part_time_func'); + Child | Tablespace +------------------------------------------+------------ + _timescaledb_internal._hyper_17_11_chunk | + _timescaledb_internal._hyper_17_12_chunk | +(2 rows) + +SELECT (test.show_constraints("Child")).* +FROM test.show_subtables('part_time_func'); + Constraint | Type | Columns | Index | Expr | Deferrable | Deferred | Validated +---------------+------+---------+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+----------+----------- + constraint_18 | c | {time} | - | ((time_partfunc("time") >= 'Wed Jun 27 17:00:00 2018 PDT'::timestamp with time zone) AND (time_partfunc("time") < 'Wed Jul 04 17:00:00 2018 PDT'::timestamp with time zone)) | f | f | t + constraint_19 | c | {time} | - | ((time_partfunc("time") >= 'Wed Aug 01 17:00:00 2018 PDT'::timestamp with time zone) AND (time_partfunc("time") < 'Wed Aug 08 17:00:00 2018 PDT'::timestamp with time zone)) | f | f | t +(2 rows) + +SELECT (test.show_indexes("Child")).* +FROM test.show_subtables('part_time_func'); + Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace +------------------------------------------------------------------+---------+---------------------+--------+---------+-----------+------------ + _timescaledb_internal._hyper_17_11_chunk_part_time_func_expr_idx | {expr} | time_partfunc(expr) | f | f | f | + _timescaledb_internal._hyper_17_12_chunk_part_time_func_expr_idx | {expr} | time_partfunc(expr) | f | f | f | +(2 rows) + +-- Check that constraint exclusion works with time partitioning +-- function (scan only one chunk) +-- No exclusion +EXPLAIN (verbose, costs off) +SELECT * FROM part_time_func; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Append + -> Seq Scan on _timescaledb_internal._hyper_17_11_chunk + Output: _hyper_17_11_chunk."time", _hyper_17_11_chunk.temp, _hyper_17_11_chunk.device + -> Seq Scan on _timescaledb_internal._hyper_17_12_chunk + Output: _hyper_17_12_chunk."time", _hyper_17_12_chunk.temp, _hyper_17_12_chunk.device +(5 rows) + +-- Exclude using the function on time +EXPLAIN (verbose, costs off) +SELECT * FROM part_time_func WHERE time_partfunc(time) < '2018-07-01'; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Index Scan using _hyper_17_11_chunk_part_time_func_expr_idx on _timescaledb_internal._hyper_17_11_chunk + Output: _hyper_17_11_chunk."time", _hyper_17_11_chunk.temp, _hyper_17_11_chunk.device + Index Cond: (time_partfunc(_hyper_17_11_chunk."time") < 'Sun Jul 01 00:00:00 2018 PDT'::timestamp with time zone) +(3 rows) + +-- Exclude using the same date but as a UNIX timestamp. Won't do an +-- index scan since the index is on the time function expression +EXPLAIN (verbose, costs off) +SELECT * FROM part_time_func WHERE time < 1530403200.0; +NOTICE: time value for 1530403200 is Sun Jul 01 00:00:00 2018 + QUERY PLAN +----------------------------------------------------------------------------------------- + Seq Scan on _timescaledb_internal._hyper_17_11_chunk + Output: _hyper_17_11_chunk."time", _hyper_17_11_chunk.temp, _hyper_17_11_chunk.device + Filter: (_hyper_17_11_chunk."time" < '1530403200'::double precision) +(3 rows) + +-- Check that inserts will fail if we use a time partitioning function +-- that returns NULL +CREATE OR REPLACE FUNCTION time_partfunc_null_ret(unixtime float8) + RETURNS TIMESTAMPTZ LANGUAGE PLPGSQL IMMUTABLE AS +$BODY$ +BEGIN + RETURN NULL; +END +$BODY$; +CREATE TABLE part_time_func_null_ret(time float8, temp float8, device text); +SELECT create_hypertable('part_time_func_null_ret', 'time', time_partitioning_func => 'time_partfunc_null_ret'); +NOTICE: adding not-null constraint to column "time" + create_hypertable +--------------------------------------- + (18,public,part_time_func_null_ret,t) +(1 row) + +\set ON_ERROR_STOP 0 +INSERT INTO part_time_func_null_ret VALUES (1530214157.134, 23.4, 'dev1'), + (1533214157.8734, 22.3, 'dev7'); +ERROR: partitioning function "public.time_partfunc_null_ret" returned NULL +\set ON_ERROR_STOP 1 diff --git a/test/expected/plan_expand_hypertable-13.out b/test/expected/plan_expand_hypertable-13.out new file mode 100644 index 000000000..96ff803c4 --- /dev/null +++ b/test/expected/plan_expand_hypertable-13.out @@ -0,0 +1,2735 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set PREFIX 'EXPLAIN (costs off) ' +\ir include/plan_expand_hypertable_load.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +--single time dimension +CREATE TABLE hyper ("time_broken" bigint NOT NULL, "value" integer); +ALTER TABLE hyper +DROP COLUMN time_broken, +ADD COLUMN time BIGINT; +SELECT create_hypertable('hyper', 'time', chunk_time_interval => 10); +psql:include/plan_expand_hypertable_load.sql:12: NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------- + (1,public,hyper,t) +(1 row) + +INSERT INTO hyper SELECT g, g FROM generate_series(0,1000) g; +--insert a point with INT_MAX_64 +INSERT INTO hyper (time, value) SELECT 9223372036854775807::bigint, 0; +--time and space +CREATE TABLE hyper_w_space ("time_broken" bigint NOT NULL, "device_id" text, "value" integer); +ALTER TABLE hyper_w_space +DROP COLUMN time_broken, +ADD COLUMN time BIGINT; +SELECT create_hypertable('hyper_w_space', 'time', 'device_id', 4, chunk_time_interval => 10); +psql:include/plan_expand_hypertable_load.sql:26: NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------- + (2,public,hyper_w_space,t) +(1 row) + +INSERT INTO hyper_w_space (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g; +CREATE VIEW hyper_w_space_view AS (SELECT * FROM hyper_w_space); +--with timestamp and space +CREATE TABLE tag (id serial PRIMARY KEY, name text); +CREATE TABLE hyper_ts ("time_broken" timestamptz NOT NULL, "device_id" text, tag_id INT REFERENCES tag(id), "value" integer); +ALTER TABLE hyper_ts +DROP COLUMN time_broken, +ADD COLUMN time TIMESTAMPTZ; +SELECT create_hypertable('hyper_ts', 'time', 'device_id', 2, chunk_time_interval => '10 seconds'::interval); +psql:include/plan_expand_hypertable_load.sql:41: NOTICE: adding not-null constraint to column "time" + create_hypertable +----------------------- + (3,public,hyper_ts,t) +(1 row) + +INSERT INTO tag(name) SELECT 'tag'||g FROM generate_series(0,10) g; +INSERT INTO hyper_ts (time, device_id, tag_id, value) SELECT to_timestamp(g), 'dev' || g, (random() /10)+1, g FROM generate_series(0,30) g; +--one in the future +INSERT INTO hyper_ts (time, device_id, tag_id, value) VALUES ('2100-01-01 02:03:04 PST', 'dev101', 1, 0); +--time partitioning function +CREATE OR REPLACE FUNCTION unix_to_timestamp(unixtime float8) + RETURNS TIMESTAMPTZ LANGUAGE SQL IMMUTABLE PARALLEL SAFE STRICT AS +$BODY$ + SELECT to_timestamp(unixtime); +$BODY$; +CREATE TABLE hyper_timefunc ("time" float8 NOT NULL, "device_id" text, "value" integer); +SELECT create_hypertable('hyper_timefunc', 'time', 'device_id', 4, chunk_time_interval => 10, time_partitioning_func => 'unix_to_timestamp'); +psql:include/plan_expand_hypertable_load.sql:57: WARNING: unexpected interval: smaller than one second + create_hypertable +----------------------------- + (4,public,hyper_timefunc,t) +(1 row) + +INSERT INTO hyper_timefunc (time, device_id, value) SELECT g, 'dev' || g, g FROM generate_series(0,30) g; +CREATE TABLE metrics_timestamp(time timestamp); +SELECT create_hypertable('metrics_timestamp','time'); +psql:include/plan_expand_hypertable_load.sql:62: NOTICE: adding not-null constraint to column "time" + create_hypertable +-------------------------------- + (5,public,metrics_timestamp,t) +(1 row) + +INSERT INTO metrics_timestamp SELECT generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'1d'::interval); +CREATE TABLE metrics_timestamptz(time timestamptz, device_id int); +SELECT create_hypertable('metrics_timestamptz','time'); +psql:include/plan_expand_hypertable_load.sql:66: NOTICE: adding not-null constraint to column "time" + create_hypertable +---------------------------------- + (6,public,metrics_timestamptz,t) +(1 row) + +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval), 1; +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval), 2; +INSERT INTO metrics_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval), 3; +--create a second table to test joins with +CREATE TABLE metrics_timestamptz_2 (LIKE metrics_timestamptz); +SELECT create_hypertable('metrics_timestamptz_2','time'); + create_hypertable +------------------------------------ + (7,public,metrics_timestamptz_2,t) +(1 row) + +INSERT INTO metrics_timestamptz_2 +SELECT * FROM metrics_timestamptz; +INSERT INTO metrics_timestamptz_2 VALUES ('2000-12-01'::timestamptz, 3); +CREATE TABLE metrics_date(time date); +SELECT create_hypertable('metrics_date','time'); +psql:include/plan_expand_hypertable_load.sql:79: NOTICE: adding not-null constraint to column "time" + create_hypertable +--------------------------- + (8,public,metrics_date,t) +(1 row) + +INSERT INTO metrics_date SELECT generate_series('2000-01-01'::date,'2000-02-01'::date,'1d'::interval); +ANALYZE hyper; +ANALYZE hyper_w_space; +ANALYZE tag; +ANALYZE hyper_ts; +ANALYZE hyper_timefunc; +-- create normal table for JOIN tests +CREATE TABLE regular_timestamptz(time timestamptz); +INSERT INTO regular_timestamptz SELECT generate_series('2000-01-01'::timestamptz,'2000-02-01'::timestamptz,'1d'::interval); +\ir include/plan_expand_hypertable_query.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +--we want to see how our logic excludes chunks +--and not how much work constraint_exclusion does +SET constraint_exclusion = 'off'; +\qecho test upper bounds +test upper bounds +:PREFIX SELECT * FROM hyper WHERE time < 10 ORDER BY value; + QUERY PLAN +------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Seq Scan on _hyper_1_1_chunk + Filter: ("time" < 10) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE time < 11 ORDER BY value; + QUERY PLAN +------------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: ("time" < 11) + -> Seq Scan on _hyper_1_2_chunk + Filter: ("time" < 11) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE time = 10 ORDER BY value; + QUERY PLAN +------------------------------------ + Sort + Sort Key: _hyper_1_2_chunk.value + -> Seq Scan on _hyper_1_2_chunk + Filter: ("time" = 10) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE 10 >= time ORDER BY value; + QUERY PLAN +------------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (10 >= "time") + -> Seq Scan on _hyper_1_2_chunk + Filter: (10 >= "time") +(7 rows) + +\qecho test lower bounds +test lower bounds +:PREFIX SELECT * FROM hyper WHERE time >= 10 and time < 20 ORDER BY value; + QUERY PLAN +---------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk.value + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" >= 10) AND ("time" < 20)) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE 10 < time and 20 >= time ORDER BY value; + QUERY PLAN +---------------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk.value + -> Append + -> Seq Scan on _hyper_1_2_chunk + Filter: ((10 < "time") AND (20 >= "time")) + -> Seq Scan on _hyper_1_3_chunk + Filter: ((10 < "time") AND (20 >= "time")) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE time >= 9 and time < 20 ORDER BY value; + QUERY PLAN +--------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 9) AND ("time" < 20)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" >= 9) AND ("time" < 20)) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE time > 9 and time < 20 ORDER BY value; + QUERY PLAN +-------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk.value + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" > 9) AND ("time" < 20)) +(4 rows) + +\qecho test empty result +test empty result +:PREFIX SELECT * FROM hyper WHERE time < 0; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +\qecho test expression evaluation +test expression evaluation +:PREFIX SELECT * FROM hyper WHERE time < (5*2)::smallint; + QUERY PLAN +------------------------------------- + Seq Scan on _hyper_1_1_chunk + Filter: ("time" < '10'::smallint) +(2 rows) + +\qecho test logic at INT64_MAX +test logic at INT64_MAX +:PREFIX SELECT * FROM hyper WHERE time = 9223372036854775807::bigint ORDER BY value; + QUERY PLAN +---------------------------------------------------------- + Sort + Sort Key: _hyper_1_102_chunk.value + -> Seq Scan on _hyper_1_102_chunk + Filter: ("time" = '9223372036854775807'::bigint) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE time = 9223372036854775806::bigint ORDER BY value; + QUERY PLAN +---------------------------------------------------------- + Sort + Sort Key: _hyper_1_102_chunk.value + -> Seq Scan on _hyper_1_102_chunk + Filter: ("time" = '9223372036854775806'::bigint) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE time >= 9223372036854775807::bigint ORDER BY value; + QUERY PLAN +----------------------------------------------------------- + Sort + Sort Key: _hyper_1_102_chunk.value + -> Seq Scan on _hyper_1_102_chunk + Filter: ("time" >= '9223372036854775807'::bigint) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE time > 9223372036854775807::bigint ORDER BY value; + QUERY PLAN +-------------------------------- + Sort + Sort Key: value + -> Result + One-Time Filter: false +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE time > 9223372036854775806::bigint ORDER BY value; + QUERY PLAN +---------------------------------------------------------- + Sort + Sort Key: _hyper_1_102_chunk.value + -> Seq Scan on _hyper_1_102_chunk + Filter: ("time" > '9223372036854775806'::bigint) +(4 rows) + +\qecho cte +cte +:PREFIX WITH cte AS( + SELECT * FROM hyper WHERE time < 10 +) +SELECT * FROM cte ORDER BY value; + QUERY PLAN +------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Seq Scan on _hyper_1_1_chunk + Filter: ("time" < 10) +(4 rows) + +\qecho subquery +subquery +:PREFIX SELECT 0 = ANY (SELECT value FROM hyper WHERE time < 10); + QUERY PLAN +-------------------------------------- + Result + SubPlan 1 + -> Seq Scan on _hyper_1_1_chunk + Filter: ("time" < 10) +(4 rows) + +\qecho no space constraint +no space constraint +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 ORDER BY value; + QUERY PLAN +-------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: ("time" < 10) + -> Seq Scan on _hyper_2_104_chunk + Filter: ("time" < 10) + -> Seq Scan on _hyper_2_105_chunk + Filter: ("time" < 10) + -> Seq Scan on _hyper_2_103_chunk + Filter: ("time" < 10) +(11 rows) + +\qecho valid space constraint +valid space constraint +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 and device_id = 'dev5' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 and 'dev5' = device_id ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND ('dev5'::text = device_id)) +(4 rows) + +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 and 'dev'||(2+3) = device_id ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND ('dev5'::text = device_id)) +(4 rows) + +\qecho only space constraint +only space constraint +:PREFIX SELECT * FROM hyper_w_space WHERE 'dev5' = device_id ORDER BY value; + QUERY PLAN +-------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: ('dev5'::text = device_id) + -> Seq Scan on _hyper_2_111_chunk + Filter: ('dev5'::text = device_id) + -> Seq Scan on _hyper_2_109_chunk + Filter: ('dev5'::text = device_id) +(9 rows) + +\qecho unhandled space constraint +unhandled space constraint +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 and device_id > 'dev5' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id > 'dev5'::text)) + -> Seq Scan on _hyper_2_104_chunk + Filter: (("time" < 10) AND (device_id > 'dev5'::text)) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND (device_id > 'dev5'::text)) + -> Seq Scan on _hyper_2_103_chunk + Filter: (("time" < 10) AND (device_id > 'dev5'::text)) +(11 rows) + +\qecho use of OR - does not filter chunks +use of OR - does not filter chunks +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND (device_id = 'dev5' or device_id = 'dev6') ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND ((device_id = 'dev5'::text) OR (device_id = 'dev6'::text))) + -> Seq Scan on _hyper_2_104_chunk + Filter: (("time" < 10) AND ((device_id = 'dev5'::text) OR (device_id = 'dev6'::text))) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND ((device_id = 'dev5'::text) OR (device_id = 'dev6'::text))) + -> Seq Scan on _hyper_2_103_chunk + Filter: (("time" < 10) AND ((device_id = 'dev5'::text) OR (device_id = 'dev6'::text))) +(11 rows) + +\qecho cte +cte +:PREFIX WITH cte AS( + SELECT * FROM hyper_w_space WHERE time < 10 and device_id = 'dev5' +) +SELECT * FROM cte ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +\qecho subquery +subquery +:PREFIX SELECT 0 = ANY (SELECT value FROM hyper_w_space WHERE time < 10 and device_id = 'dev5'); + QUERY PLAN +------------------------------------------------------------------ + Result + SubPlan 1 + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +\qecho view +view +:PREFIX SELECT * FROM hyper_w_space_view WHERE time < 10 and device_id = 'dev5' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +\qecho IN statement - simple +IN statement - simple +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id IN ('dev5') ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +\qecho IN statement - two chunks +IN statement - two chunks +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id IN ('dev5','dev6') ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev5,dev6}'::text[]))) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev5,dev6}'::text[]))) +(7 rows) + +\qecho IN statement - one chunk +IN statement - one chunk +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id IN ('dev4','dev5') ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev4,dev5}'::text[]))) +(4 rows) + +\qecho NOT IN - does not filter chunks +NOT IN - does not filter chunks +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id NOT IN ('dev5','dev6') ORDER BY value; + QUERY PLAN +-------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id <> ALL ('{dev5,dev6}'::text[]))) + -> Seq Scan on _hyper_2_104_chunk + Filter: (("time" < 10) AND (device_id <> ALL ('{dev5,dev6}'::text[]))) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND (device_id <> ALL ('{dev5,dev6}'::text[]))) + -> Seq Scan on _hyper_2_103_chunk + Filter: (("time" < 10) AND (device_id <> ALL ('{dev5,dev6}'::text[]))) +(11 rows) + +\qecho IN statement with subquery - does not filter chunks +IN statement with subquery - does not filter chunks +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id IN (SELECT 'dev5'::text) ORDER BY value; + QUERY PLAN +---------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = 'dev5'::text)) +(4 rows) + +\qecho ANY +ANY +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id = ANY(ARRAY['dev5','dev6']) ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev5,dev6}'::text[]))) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev5,dev6}'::text[]))) +(7 rows) + +\qecho ANY with intersection +ANY with intersection +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id = ANY(ARRAY['dev5','dev6']) AND device_id = ANY(ARRAY['dev6','dev7']) ORDER BY value; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_105_chunk.value + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND (device_id = ANY ('{dev5,dev6}'::text[])) AND (device_id = ANY ('{dev6,dev7}'::text[]))) +(4 rows) + +\qecho ANY without intersection shouldnt scan any chunks +ANY without intersection shouldnt scan any chunks +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND device_id = ANY(ARRAY['dev5','dev6']) AND device_id = ANY(ARRAY['dev8','dev9']) ORDER BY value; + QUERY PLAN +-------------------------------- + Sort + Sort Key: value + -> Result + One-Time Filter: false +(4 rows) + +\qecho ANY/IN/ALL only works for equals operator +ANY/IN/ALL only works for equals operator +:PREFIX SELECT * FROM hyper_w_space WHERE device_id < ANY(ARRAY['dev5','dev6']) ORDER BY value; + QUERY PLAN +----------------------------------------------------------------- + Sort + Sort Key: _hyper_2_103_chunk.value + -> Append + -> Seq Scan on _hyper_2_103_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_104_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_105_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_106_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_107_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_108_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_109_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_110_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_111_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_112_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_113_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_114_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) + -> Seq Scan on _hyper_2_115_chunk + Filter: (device_id < ANY ('{dev5,dev6}'::text[])) +(29 rows) + +\qecho ALL with equals and different values shouldnt scan any chunks +ALL with equals and different values shouldnt scan any chunks +:PREFIX SELECT * FROM hyper_w_space WHERE device_id = ALL(ARRAY['dev5','dev6']) ORDER BY value; + QUERY PLAN +-------------------------------- + Sort + Sort Key: value + -> Result + One-Time Filter: false +(4 rows) + +\qecho Multi AND +Multi AND +:PREFIX SELECT * FROM hyper_w_space WHERE time < 10 AND time < 100 ORDER BY value; + QUERY PLAN +---------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: (("time" < 10) AND ("time" < 100)) + -> Seq Scan on _hyper_2_104_chunk + Filter: (("time" < 10) AND ("time" < 100)) + -> Seq Scan on _hyper_2_105_chunk + Filter: (("time" < 10) AND ("time" < 100)) + -> Seq Scan on _hyper_2_103_chunk + Filter: (("time" < 10) AND ("time" < 100)) +(11 rows) + +\qecho Time dimension doesnt filter chunks when using IN/ANY with multiple arguments +Time dimension doesnt filter chunks when using IN/ANY with multiple arguments +:PREFIX SELECT * FROM hyper_w_space WHERE time < ANY(ARRAY[1,2]) ORDER BY value; + QUERY PLAN +----------------------------------------------------------- + Sort + Sort Key: _hyper_2_103_chunk.value + -> Append + -> Seq Scan on _hyper_2_103_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_104_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_105_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_106_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_107_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_108_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_109_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_110_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_111_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_112_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_113_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_114_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) + -> Seq Scan on _hyper_2_115_chunk + Filter: ("time" < ANY ('{1,2}'::integer[])) +(29 rows) + +\qecho Time dimension chunk filtering works for ANY with single argument +Time dimension chunk filtering works for ANY with single argument +:PREFIX SELECT * FROM hyper_w_space WHERE time < ANY(ARRAY[1]) ORDER BY value; + QUERY PLAN +--------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: ("time" < ANY ('{1}'::integer[])) + -> Seq Scan on _hyper_2_104_chunk + Filter: ("time" < ANY ('{1}'::integer[])) + -> Seq Scan on _hyper_2_105_chunk + Filter: ("time" < ANY ('{1}'::integer[])) + -> Seq Scan on _hyper_2_103_chunk + Filter: ("time" < ANY ('{1}'::integer[])) +(11 rows) + +\qecho Time dimension chunk filtering works for ALL with single argument +Time dimension chunk filtering works for ALL with single argument +:PREFIX SELECT * FROM hyper_w_space WHERE time < ALL(ARRAY[1]) ORDER BY value; + QUERY PLAN +--------------------------------------------------------- + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: ("time" < ALL ('{1}'::integer[])) + -> Seq Scan on _hyper_2_104_chunk + Filter: ("time" < ALL ('{1}'::integer[])) + -> Seq Scan on _hyper_2_105_chunk + Filter: ("time" < ALL ('{1}'::integer[])) + -> Seq Scan on _hyper_2_103_chunk + Filter: ("time" < ALL ('{1}'::integer[])) +(11 rows) + +\qecho Time dimension chunk filtering works for ALL with multiple arguments +Time dimension chunk filtering works for ALL with multiple arguments +:PREFIX SELECT * FROM hyper_w_space WHERE time < ALL(ARRAY[1,10,20,30]) ORDER BY value; + QUERY PLAN +------------------------------------------------------------------ + Sort + Sort Key: _hyper_2_106_chunk.value + -> Append + -> Seq Scan on _hyper_2_106_chunk + Filter: ("time" < ALL ('{1,10,20,30}'::integer[])) + -> Seq Scan on _hyper_2_104_chunk + Filter: ("time" < ALL ('{1,10,20,30}'::integer[])) + -> Seq Scan on _hyper_2_105_chunk + Filter: ("time" < ALL ('{1,10,20,30}'::integer[])) + -> Seq Scan on _hyper_2_103_chunk + Filter: ("time" < ALL ('{1,10,20,30}'::integer[])) +(11 rows) + +\qecho AND intersection using IN and EQUALS +AND intersection using IN and EQUALS +:PREFIX SELECT * FROM hyper_w_space WHERE device_id IN ('dev1','dev2') AND device_id = 'dev1' ORDER BY value; + QUERY PLAN +-------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_2_103_chunk.value + -> Append + -> Seq Scan on _hyper_2_103_chunk + Filter: ((device_id = ANY ('{dev1,dev2}'::text[])) AND (device_id = 'dev1'::text)) + -> Seq Scan on _hyper_2_110_chunk + Filter: ((device_id = ANY ('{dev1,dev2}'::text[])) AND (device_id = 'dev1'::text)) + -> Seq Scan on _hyper_2_114_chunk + Filter: ((device_id = ANY ('{dev1,dev2}'::text[])) AND (device_id = 'dev1'::text)) +(9 rows) + +\qecho AND with no intersection using IN and EQUALS +AND with no intersection using IN and EQUALS +:PREFIX SELECT * FROM hyper_w_space WHERE device_id IN ('dev1','dev2') AND device_id = 'dev3' ORDER BY value; + QUERY PLAN +-------------------------------- + Sort + Sort Key: value + -> Result + One-Time Filter: false +(4 rows) + +\qecho timestamps +timestamps +\qecho these should work since they are immutable functions +these should work since they are immutable functions +:PREFIX SELECT * FROM hyper_ts WHERE time < 'Wed Dec 31 16:00:10 1969 PST'::timestamptz ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_117_chunk.value + -> Append + -> Seq Scan on _hyper_3_117_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_3_116_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) +(7 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE time < to_timestamp(10) ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_117_chunk.value + -> Append + -> Seq Scan on _hyper_3_117_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_3_116_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) +(7 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE time < 'Wed Dec 31 16:00:10 1969'::timestamp AT TIME ZONE 'PST' ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_117_chunk.value + -> Append + -> Seq Scan on _hyper_3_117_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_3_116_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) +(7 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE time < to_timestamp(10) and device_id = 'dev1' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) +(4 rows) + +\qecho these should not work since uses stable functions; +these should not work since uses stable functions; +:PREFIX SELECT * FROM hyper_ts WHERE time < 'Wed Dec 31 16:00:10 1969'::timestamp ORDER BY value; + QUERY PLAN +------------------------------------------------------------------------------------------ + Sort + Sort Key: hyper_ts.value + -> Custom Scan (ChunkAppend) on hyper_ts + Chunks excluded during startup: 6 + -> Seq Scan on _hyper_3_116_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969'::timestamp without time zone) + -> Seq Scan on _hyper_3_117_chunk + Filter: ("time" < 'Wed Dec 31 16:00:10 1969'::timestamp without time zone) +(8 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE time < ('Wed Dec 31 16:00:10 1969'::timestamp::timestamptz) ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: hyper_ts.value + -> Custom Scan (ChunkAppend) on hyper_ts + Chunks excluded during startup: 6 + -> Seq Scan on _hyper_3_116_chunk + Filter: ("time" < ('Wed Dec 31 16:00:10 1969'::timestamp without time zone)::timestamp with time zone) + -> Seq Scan on _hyper_3_117_chunk + Filter: ("time" < ('Wed Dec 31 16:00:10 1969'::timestamp without time zone)::timestamp with time zone) +(8 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE NOW() < time ORDER BY value; + QUERY PLAN +--------------------------------------------- + Sort + Sort Key: hyper_ts.value + -> Custom Scan (ChunkAppend) on hyper_ts + Chunks excluded during startup: 7 + -> Seq Scan on _hyper_3_123_chunk + Filter: (now() < "time") +(6 rows) + +\qecho joins +joins +:PREFIX SELECT * FROM hyper_ts WHERE tag_id IN (SELECT id FROM tag WHERE tag.id=1) and time < to_timestamp(10) and device_id = 'dev1' ORDER BY value; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Nested Loop Semi Join + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text) AND (tag_id = 1)) + -> Seq Scan on tag + Filter: (id = 1) +(7 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE tag_id IN (SELECT id FROM tag WHERE tag.id=1) or (time < to_timestamp(10) and device_id = 'dev1') ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: hyper_ts.value + -> Custom Scan (ChunkAppend) on hyper_ts + -> Seq Scan on _hyper_3_116_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + SubPlan 1 + -> Seq Scan on tag + Filter: (id = 1) + -> Seq Scan on _hyper_3_117_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_118_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_119_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_120_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_121_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_122_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) + -> Seq Scan on _hyper_3_123_chunk + Filter: ((hashed SubPlan 1) OR (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text))) +(22 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE tag_id IN (SELECT id FROM tag WHERE tag.name='tag1') and time < to_timestamp(10) and device_id = 'dev1' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Nested Loop + Join Filter: (_hyper_3_116_chunk.tag_id = tag.id) + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) + -> Seq Scan on tag + Filter: (name = 'tag1'::text) +(8 rows) + +:PREFIX SELECT * FROM hyper_ts JOIN tag on (hyper_ts.tag_id = tag.id ) WHERE time < to_timestamp(10) and device_id = 'dev1' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Merge Join + Merge Cond: (tag.id = _hyper_3_116_chunk.tag_id) + -> Index Scan using tag_pkey on tag + -> Sort + Sort Key: _hyper_3_116_chunk.tag_id + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) +(9 rows) + +:PREFIX SELECT * FROM hyper_ts JOIN tag on (hyper_ts.tag_id = tag.id ) WHERE tag.name = 'tag1' and time < to_timestamp(10) and device_id = 'dev1' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Nested Loop + Join Filter: (_hyper_3_116_chunk.tag_id = tag.id) + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) + -> Seq Scan on tag + Filter: (name = 'tag1'::text) +(8 rows) + +\qecho test constraint exclusion for constraints in ON clause of JOINs +test constraint exclusion for constraints in ON clause of JOINs +\qecho should exclude chunks on m1 and propagate qual to m2 because of INNER JOIN +should exclude chunks on m1 and propagate qual to m2 because of INNER JOIN +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +\qecho should exclude chunks on m2 and propagate qual to m1 because of INNER JOIN +should exclude chunks on m2 and propagate qual to m1 because of INNER JOIN +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +\qecho must not exclude on m1 +must not exclude on m1 +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (m1."time" = m2."time") + Join Filter: (m1."time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(19 rows) + +\qecho should exclude chunks on m2 +should exclude chunks on m2 +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(24 rows) + +\qecho should exclude chunks on m1 +should exclude chunks on m1 +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: m1."time" + -> Merge Right Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(25 rows) + +\qecho must not exclude chunks on m2 +must not exclude chunks on m2 +:PREFIX SELECT m1.time,m2.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: m1."time" + -> Merge Left Join + Merge Cond: (m2."time" = m1."time") + Join Filter: (m2."time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 +(21 rows) + +\qecho time_bucket exclusion +time_bucket exclusion +:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 10::bigint ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk."time" + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < '20'::bigint) AND (time_bucket('10'::bigint, "time") < '10'::bigint)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < '20'::bigint) AND (time_bucket('10'::bigint, "time") < '10'::bigint)) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) < 11::bigint ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk."time" + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < '21'::bigint) AND (time_bucket('10'::bigint, "time") < '11'::bigint)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < '21'::bigint) AND (time_bucket('10'::bigint, "time") < '11'::bigint)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" < '21'::bigint) AND (time_bucket('10'::bigint, "time") < '11'::bigint)) +(9 rows) + +:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) <= 10::bigint ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk."time" + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" <= '20'::bigint) AND (time_bucket('10'::bigint, "time") <= '10'::bigint)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" <= '20'::bigint) AND (time_bucket('10'::bigint, "time") <= '10'::bigint)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" <= '20'::bigint) AND (time_bucket('10'::bigint, "time") <= '10'::bigint)) +(9 rows) + +:PREFIX SELECT * FROM hyper WHERE 10::bigint > time_bucket(10, time) ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk."time" + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < '20'::bigint) AND ('10'::bigint > time_bucket('10'::bigint, "time"))) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < '20'::bigint) AND ('10'::bigint > time_bucket('10'::bigint, "time"))) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE 11::bigint > time_bucket(10, time) ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk."time" + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < '21'::bigint) AND ('11'::bigint > time_bucket('10'::bigint, "time"))) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < '21'::bigint) AND ('11'::bigint > time_bucket('10'::bigint, "time"))) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" < '21'::bigint) AND ('11'::bigint > time_bucket('10'::bigint, "time"))) +(9 rows) + +\qecho test overflow behaviour of time_bucket exclusion +test overflow behaviour of time_bucket exclusion +:PREFIX SELECT * FROM hyper WHERE time > 950 AND time_bucket(10, time) < '9223372036854775807'::bigint ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_96_chunk."time" + -> Append + -> Seq Scan on _hyper_1_96_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_97_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_98_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_99_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_100_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_101_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) + -> Seq Scan on _hyper_1_102_chunk + Filter: (("time" > 950) AND (time_bucket('10'::bigint, "time") < '9223372036854775807'::bigint)) +(17 rows) + +\qecho test timestamp upper boundary +test timestamp upper boundary +\qecho there should be no transformation if we are out of the supported (TimescaleDB-specific) range +there should be no transformation if we are out of the supported (TimescaleDB-specific) range +:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '294276-01-01'::timestamp ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------ + Custom Scan (ChunkAppend) on metrics_timestamp + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_156_chunk_metrics_timestamp_time_idx on _hyper_5_156_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_157_chunk_metrics_timestamp_time_idx on _hyper_5_157_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_158_chunk_metrics_timestamp_time_idx on _hyper_5_158_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_159_chunk_metrics_timestamp_time_idx on _hyper_5_159_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) +(12 rows) + +\qecho transformation would be out of range +transformation would be out of range +:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1000d',time) < '294276-01-01'::timestamp ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_156_chunk_metrics_timestamp_time_idx on _hyper_5_156_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_157_chunk_metrics_timestamp_time_idx on _hyper_5_157_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_158_chunk_metrics_timestamp_time_idx on _hyper_5_158_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) + -> Index Only Scan Backward using _hyper_5_159_chunk_metrics_timestamp_time_idx on _hyper_5_159_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276'::timestamp without time zone) +(12 rows) + +\qecho test timestamptz upper boundary +test timestamptz upper boundary +\qecho there should be no transformation if we are out of the supported (TimescaleDB-specific) range +there should be no transformation if we are out of the supported (TimescaleDB-specific) range +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) < '294276-01-01'::timestamptz ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) +(12 rows) + +\qecho transformation would be out of range +transformation would be out of range +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1000d',time) < '294276-01-01'::timestamptz ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk + Filter: (time_bucket('@ 1000 days'::interval, "time") < 'Sat Jan 01 00:00:00 294276 PST'::timestamp with time zone) +(12 rows) + +:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 100 ORDER BY time; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk."time" + -> Append + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_4_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_5_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_6_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_7_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_8_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_9_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_10_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_11_chunk + Filter: (("time" > 10) AND ("time" < '110'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 100)) +(23 rows) + +:PREFIX SELECT * FROM hyper WHERE time_bucket(10, time) > 10 AND time_bucket(10, time) < 20 ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk."time" + -> Append + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" > 10) AND ("time" < '30'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" > 10) AND ("time" < '30'::bigint) AND (time_bucket('10'::bigint, "time") > 10) AND (time_bucket('10'::bigint, "time") < 20)) +(7 rows) + +:PREFIX SELECT * FROM hyper WHERE time_bucket(1, time) > 11 AND time_bucket(1, time) < 19 ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk."time" + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" > 11) AND ("time" < '20'::bigint) AND (time_bucket('1'::bigint, "time") > 11) AND (time_bucket('1'::bigint, "time") < 19)) +(4 rows) + +:PREFIX SELECT * FROM hyper WHERE 10 < time_bucket(10, time) AND 20 > time_bucket(10,time) ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_1_2_chunk."time" + -> Append + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" > 10) AND ("time" < '30'::bigint) AND (10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time"))) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" > 10) AND ("time" < '30'::bigint) AND (10 < time_bucket('10'::bigint, "time")) AND (20 > time_bucket('10'::bigint, "time"))) +(7 rows) + +\qecho time_bucket exclusion with date +time_bucket exclusion with date +:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------- + Index Only Scan Backward using _hyper_8_171_chunk_metrics_date_time_idx on _hyper_8_171_chunk + Index Cond: ("time" < '01-04-2000'::date) + Filter: (time_bucket('@ 1 day'::interval, "time") < '01-03-2000'::date) +(3 rows) + +:PREFIX SELECT * FROM metrics_date WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_date + Order: metrics_date."time" + -> Index Only Scan Backward using _hyper_8_171_chunk_metrics_date_time_idx on _hyper_8_171_chunk + Index Cond: (("time" >= '01-03-2000'::date) AND ("time" <= '01-11-2000'::date)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date)) + -> Index Only Scan Backward using _hyper_8_172_chunk_metrics_date_time_idx on _hyper_8_172_chunk + Index Cond: (("time" >= '01-03-2000'::date) AND ("time" <= '01-11-2000'::date)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= '01-03-2000'::date) AND (time_bucket('@ 1 day'::interval, "time") <= '01-10-2000'::date)) +(8 rows) + +\qecho time_bucket exclusion with timestamp +time_bucket exclusion with timestamp +:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------- + Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk + Index Cond: ("time" < 'Tue Jan 04 00:00:00 2000'::timestamp without time zone) + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) +(3 rows) + +:PREFIX SELECT * FROM metrics_timestamp WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamp + Order: metrics_timestamp."time" + -> Index Only Scan Backward using _hyper_5_155_chunk_metrics_timestamp_time_idx on _hyper_5_155_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND ("time" <= 'Tue Jan 11 00:00:00 2000'::timestamp without time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone)) + -> Index Only Scan Backward using _hyper_5_156_chunk_metrics_timestamp_time_idx on _hyper_5_156_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND ("time" <= 'Tue Jan 11 00:00:00 2000'::timestamp without time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000'::timestamp without time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000'::timestamp without time zone)) +(8 rows) + +\qecho time_bucket exclusion with timestamptz +time_bucket exclusion with timestamptz +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('6h',time) < '2000-01-03' ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Index Cond: ("time" < 'Mon Jan 03 06:00:00 2000 PST'::timestamp with time zone) + Filter: (time_bucket('@ 6 hours'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('6h',time) >= '2000-01-03' AND time_bucket('6h',time) <= '2000-01-10' ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Mon Jan 10 06:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Mon Jan 10 06:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 6 hours'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 6 hours'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(8 rows) + +\qecho time_bucket exclusion with timestamptz and day interval +time_bucket exclusion with timestamptz and day interval +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) < '2000-01-03' ORDER BY time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------- + Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Index Cond: ("time" < 'Tue Jan 04 00:00:00 2000 PST'::timestamp with time zone) + Filter: (time_bucket('@ 1 day'::interval, "time") < 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) +(3 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Tue Jan 11 00:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Tue Jan 11 00:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 1 day'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(8 rows) + +:PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Custom Scan (ChunkAppend) on metrics_timestamptz + Order: metrics_timestamptz."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Mon Jan 17 00:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Mon Jan 17 00:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk + Index Cond: (("time" >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND ("time" <= 'Mon Jan 17 00:00:00 2000 PST'::timestamp with time zone)) + Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(11 rows) + +\qecho exclude chunks based on time column with partitioning function. This +exclude chunks based on time column with partitioning function. This +\qecho transparently applies the time partitioning function on the time +transparently applies the time partitioning function on the time +\qecho value to be able to exclude chunks (similar to a closed dimension). +value to be able to exclude chunks (similar to a closed dimension). +:PREFIX SELECT * FROM hyper_timefunc WHERE time < 4 ORDER BY value; + QUERY PLAN +-------------------------------------------------------- + Sort + Sort Key: _hyper_4_125_chunk.value + -> Append + -> Seq Scan on _hyper_4_125_chunk + Filter: ("time" < '4'::double precision) + -> Seq Scan on _hyper_4_126_chunk + Filter: ("time" < '4'::double precision) + -> Seq Scan on _hyper_4_127_chunk + Filter: ("time" < '4'::double precision) + -> Seq Scan on _hyper_4_124_chunk + Filter: ("time" < '4'::double precision) +(11 rows) + +\qecho excluding based on time expression is currently unoptimized +excluding based on time expression is currently unoptimized +:PREFIX SELECT * FROM hyper_timefunc WHERE unix_to_timestamp(time) < 'Wed Dec 31 16:00:04 1969 PST' ORDER BY value; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_4_124_chunk.value + -> Append + -> Seq Scan on _hyper_4_124_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_125_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_126_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_127_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_128_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_129_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_130_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_131_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_132_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_133_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_134_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_135_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_136_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_137_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_138_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_139_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_140_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_141_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_142_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_143_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_144_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_145_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_146_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_147_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_148_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_149_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_150_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_151_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_152_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_153_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) + -> Seq Scan on _hyper_4_154_chunk + Filter: (to_timestamp("time") < 'Wed Dec 31 16:00:04 1969 PST'::timestamp with time zone) +(65 rows) + +\qecho test qual propagation for joins +test qual propagation for joins +RESET constraint_exclusion; +\qecho nothing to propagate +nothing to propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1, metrics_timestamptz_2 m2 WHERE m1.time = m2.time ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(18 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(18 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(18 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: m1."time" + -> Merge Right Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(20 rows) + +\qecho OR constraints should not propagate +OR constraints should not propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10' OR m1.time > '2001-01-01' ORDER BY m1.time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Filter: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) OR ("time" > 'Mon Jan 01 00:00:00 2001 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Filter: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) OR ("time" > 'Mon Jan 01 00:00:00 2001 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(17 rows) + +\qecho test single constraint +test single constraint +\qecho constraint should be on both scans +constraint should be on both scans +\qecho these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +:PREFIX SELECT m1.time FROM metrics_timestamptz m1, metrics_timestamptz_2 m2 WHERE m1.time = m2.time AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(17 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +\qecho test 2 constraints on single relation +test 2 constraints on single relation +\qecho these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +:PREFIX SELECT m1.time FROM metrics_timestamptz m1, metrics_timestamptz_2 m2 WHERE m1.time = m2.time AND m1.time > '2000-01-01' AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop Left Join + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Append + -> Index Only Scan using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 + Index Cond: ("time" = m1."time") +(20 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +\qecho test 2 constraints with 1 constraint on each relation +test 2 constraints with 1 constraint on each relation +\qecho these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +these will propagate even for LEFT/RIGHT JOIN because the constraints are not in the ON clause and therefore imply a NOT NULL condition on the JOIN column +:PREFIX SELECT m1.time FROM metrics_timestamptz m1, metrics_timestamptz_2 m2 WHERE m1.time = m2.time AND m1.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) AND ("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +\qecho test constraints in ON clause of INNER JOIN +test constraints in ON clause of INNER JOIN +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(15 rows) + +\qecho test constraints in ON clause of LEFT JOIN +test constraints in ON clause of LEFT JOIN +\qecho must not propagate +must not propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 LEFT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Merge Left Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(16 rows) + +\qecho test constraints in ON clause of RIGHT JOIN +test constraints in ON clause of RIGHT JOIN +\qecho must not propagate +must not propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 RIGHT JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time AND m2.time > '2000-01-01' AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Gather Merge + Workers Planned: 2 + -> Sort + Sort Key: m1_1."time" + -> Parallel Hash Left Join + Hash Cond: (m2_1."time" = m1_1."time") + Join Filter: ((m2_1."time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND (m2_1."time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Parallel Append + -> Parallel Seq Scan on _hyper_7_165_chunk m2_1 + -> Parallel Seq Scan on _hyper_7_166_chunk m2_2 + -> Parallel Seq Scan on _hyper_7_167_chunk m2_3 + -> Parallel Seq Scan on _hyper_7_168_chunk m2_4 + -> Parallel Seq Scan on _hyper_7_169_chunk m2_5 + -> Parallel Seq Scan on _hyper_7_170_chunk m2_6 + -> Parallel Hash + -> Parallel Append + -> Parallel Seq Scan on _hyper_6_160_chunk m1_1 + -> Parallel Seq Scan on _hyper_6_161_chunk m1_2 + -> Parallel Seq Scan on _hyper_6_162_chunk m1_3 + -> Parallel Seq Scan on _hyper_6_163_chunk m1_4 + -> Parallel Seq Scan on _hyper_6_164_chunk m1_5 +(21 rows) + +\qecho test equality condition not in ON clause +test equality condition not in ON clause +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON true WHERE m2.time = m1.time AND m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(15 rows) + +\qecho test constraints not joined on +test constraints not joined on +\qecho device_id constraint must not propagate +device_id constraint must not propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON true WHERE m2.time = m1.time AND m2.time < '2000-01-10' AND m1.device_id = 1 ORDER BY m1.time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Nested Loop + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = 1) + -> Index Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = 1) + -> Append + -> Index Only Scan using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" = m1."time") AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" = m1."time") AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) +(14 rows) + +\qecho test multiple join conditions +test multiple join conditions +\qecho device_id constraint should propagate +device_id constraint should propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON true WHERE m2.time = m1.time AND m1.device_id = m2.device_id AND m2.time < '2000-01-10' AND m1.device_id = 1 ORDER BY m1.time; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- + Nested Loop + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = 1) + -> Index Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + Filter: (device_id = 1) + -> Append + -> Index Scan using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" = m1."time") AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Filter: (device_id = 1) + -> Index Scan using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" = m1."time") AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + Filter: (device_id = 1) +(16 rows) + +\qecho test join with 3 tables +test join with 3 tables +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time INNER JOIN metrics_timestamptz m3 ON m2.time=m3.time WHERE m1.time > '2000-01-01' AND m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + -> Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: (("time" > 'Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone) AND ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) + -> Append + -> Index Only Scan using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m3_1 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m3_2 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m3_3 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m3_4 + Index Cond: ("time" = m1."time") + -> Index Only Scan using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m3_5 + Index Cond: ("time" = m1."time") +(27 rows) + +\qecho test non-Const constraints +test non-Const constraints +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10'::text::timestamptz ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + Chunks excluded during startup: 3 + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + Chunks excluded during startup: 4 + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < ('2000-01-10'::cstring)::timestamp with time zone) +(17 rows) + +\qecho test now() +test now() +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < now() ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + Chunks excluded during startup: 0 + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + Index Cond: ("time" < now()) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + Chunks excluded during startup: 0 + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + Index Cond: ("time" < now()) + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 + Index Cond: ("time" < now()) +(31 rows) + +\qecho test volatile function +test volatile function +\qecho should not propagate +should not propagate +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m1.time < clock_timestamp() ORDER BY m1.time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + Chunks excluded during startup: 0 + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 + Filter: ("time" < clock_timestamp()) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 +(24 rows) + +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN metrics_timestamptz_2 m2 ON m1.time = m2.time WHERE m2.time < clock_timestamp() ORDER BY m1.time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m2."time" = m1."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz_2 m2 + Order: m2."time" + Chunks excluded during startup: 0 + -> Index Only Scan Backward using _hyper_7_165_chunk_metrics_timestamptz_2_time_idx on _hyper_7_165_chunk m2_1 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_7_166_chunk_metrics_timestamptz_2_time_idx on _hyper_7_166_chunk m2_2 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_7_167_chunk_metrics_timestamptz_2_time_idx on _hyper_7_167_chunk m2_3 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_7_168_chunk_metrics_timestamptz_2_time_idx on _hyper_7_168_chunk m2_4 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_7_169_chunk_metrics_timestamptz_2_time_idx on _hyper_7_169_chunk m2_5 + Filter: ("time" < clock_timestamp()) + -> Index Only Scan Backward using _hyper_7_170_chunk_metrics_timestamptz_2_time_idx on _hyper_7_170_chunk m2_6 + Filter: ("time" < clock_timestamp()) + -> Materialize + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + -> Index Only Scan Backward using _hyper_6_162_chunk_metrics_timestamptz_time_idx on _hyper_6_162_chunk m1_3 + -> Index Only Scan Backward using _hyper_6_163_chunk_metrics_timestamptz_time_idx on _hyper_6_163_chunk m1_4 + -> Index Only Scan Backward using _hyper_6_164_chunk_metrics_timestamptz_time_idx on _hyper_6_164_chunk m1_5 +(25 rows) + +\qecho test JOINs with normal table +test JOINs with normal table +\qecho will not propagate because constraints are only added to hypertables +will not propagate because constraints are only added to hypertables +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN regular_timestamptz m2 ON m1.time = m2.time WHERE m1.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Sort + Sort Key: m2."time" + -> Seq Scan on regular_timestamptz m2 +(11 rows) + +\qecho test JOINs with normal table +test JOINs with normal table +:PREFIX SELECT m1.time FROM metrics_timestamptz m1 INNER JOIN regular_timestamptz m2 ON m1.time = m2.time WHERE m2.time < '2000-01-10' ORDER BY m1.time; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Merge Join + Merge Cond: (m1."time" = m2."time") + -> Custom Scan (ChunkAppend) on metrics_timestamptz m1 + Order: m1."time" + -> Index Only Scan Backward using _hyper_6_160_chunk_metrics_timestamptz_time_idx on _hyper_6_160_chunk m1_1 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Index Only Scan Backward using _hyper_6_161_chunk_metrics_timestamptz_time_idx on _hyper_6_161_chunk m1_2 + Index Cond: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) + -> Sort + Sort Key: m2."time" + -> Seq Scan on regular_timestamptz m2 + Filter: ("time" < 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone) +(12 rows) + +\qecho test quals are not pushed into OUTER JOIN +test quals are not pushed into OUTER JOIN +CREATE TABLE outer_join_1 (id int, name text,time timestamptz NOT NULL DEFAULT '2000-01-01'); +CREATE TABLE outer_join_2 (id int, name text,time timestamptz NOT NULL DEFAULT '2000-01-01'); +SELECT (SELECT table_name FROM create_hypertable(tbl, 'time')) FROM (VALUES ('outer_join_1'),('outer_join_2')) v(tbl); + table_name +-------------- + outer_join_1 + outer_join_2 +(2 rows) + +INSERT INTO outer_join_1 VALUES(1,'a'), (2,'b'); +INSERT INTO outer_join_2 VALUES(1,'a'); +:PREFIX SELECT one.id, two.name FROM outer_join_1 one LEFT OUTER JOIN outer_join_2 two ON one.id=two.id WHERE one.id=2; + QUERY PLAN +------------------------------------------------- + Nested Loop Left Join + Join Filter: (one.id = two.id) + -> Seq Scan on _hyper_9_176_chunk one + Filter: (id = 2) + -> Materialize + -> Seq Scan on _hyper_10_177_chunk two + Filter: (id = 2) +(7 rows) + +:PREFIX SELECT one.id, two.name FROM outer_join_2 two RIGHT OUTER JOIN outer_join_1 one ON one.id=two.id WHERE one.id=2; + QUERY PLAN +------------------------------------------------- + Nested Loop Left Join + Join Filter: (one.id = two.id) + -> Seq Scan on _hyper_9_176_chunk one + Filter: (id = 2) + -> Materialize + -> Seq Scan on _hyper_10_177_chunk two + Filter: (id = 2) +(7 rows) + +DROP TABLE outer_join_1; +DROP TABLE outer_join_2; +-- test UNION between regular table and hypertable +SELECT time FROM regular_timestamptz UNION SELECT time FROM metrics_timestamptz ORDER BY 1; + time +------------------------------ + Sat Jan 01 00:00:00 2000 PST + Sun Jan 02 00:00:00 2000 PST + Mon Jan 03 00:00:00 2000 PST + Tue Jan 04 00:00:00 2000 PST + Wed Jan 05 00:00:00 2000 PST + Thu Jan 06 00:00:00 2000 PST + Fri Jan 07 00:00:00 2000 PST + Sat Jan 08 00:00:00 2000 PST + Sun Jan 09 00:00:00 2000 PST + Mon Jan 10 00:00:00 2000 PST + Tue Jan 11 00:00:00 2000 PST + Wed Jan 12 00:00:00 2000 PST + Thu Jan 13 00:00:00 2000 PST + Fri Jan 14 00:00:00 2000 PST + Sat Jan 15 00:00:00 2000 PST + Sun Jan 16 00:00:00 2000 PST + Mon Jan 17 00:00:00 2000 PST + Tue Jan 18 00:00:00 2000 PST + Wed Jan 19 00:00:00 2000 PST + Thu Jan 20 00:00:00 2000 PST + Fri Jan 21 00:00:00 2000 PST + Sat Jan 22 00:00:00 2000 PST + Sun Jan 23 00:00:00 2000 PST + Mon Jan 24 00:00:00 2000 PST + Tue Jan 25 00:00:00 2000 PST + Wed Jan 26 00:00:00 2000 PST + Thu Jan 27 00:00:00 2000 PST + Fri Jan 28 00:00:00 2000 PST + Sat Jan 29 00:00:00 2000 PST + Sun Jan 30 00:00:00 2000 PST + Mon Jan 31 00:00:00 2000 PST + Tue Feb 01 00:00:00 2000 PST +(32 rows) + +-- test UNION ALL between regular table and hypertable +SELECT time FROM regular_timestamptz UNION ALL SELECT time FROM metrics_timestamptz ORDER BY 1; + time +------------------------------ + Sat Jan 01 00:00:00 2000 PST + Sat Jan 01 00:00:00 2000 PST + Sat Jan 01 00:00:00 2000 PST + Sat Jan 01 00:00:00 2000 PST + Sun Jan 02 00:00:00 2000 PST + Sun Jan 02 00:00:00 2000 PST + Sun Jan 02 00:00:00 2000 PST + Sun Jan 02 00:00:00 2000 PST + Mon Jan 03 00:00:00 2000 PST + Mon Jan 03 00:00:00 2000 PST + Mon Jan 03 00:00:00 2000 PST + Mon Jan 03 00:00:00 2000 PST + Tue Jan 04 00:00:00 2000 PST + Tue Jan 04 00:00:00 2000 PST + Tue Jan 04 00:00:00 2000 PST + Tue Jan 04 00:00:00 2000 PST + Wed Jan 05 00:00:00 2000 PST + Wed Jan 05 00:00:00 2000 PST + Wed Jan 05 00:00:00 2000 PST + Wed Jan 05 00:00:00 2000 PST + Thu Jan 06 00:00:00 2000 PST + Thu Jan 06 00:00:00 2000 PST + Thu Jan 06 00:00:00 2000 PST + Thu Jan 06 00:00:00 2000 PST + Fri Jan 07 00:00:00 2000 PST + Fri Jan 07 00:00:00 2000 PST + Fri Jan 07 00:00:00 2000 PST + Fri Jan 07 00:00:00 2000 PST + Sat Jan 08 00:00:00 2000 PST + Sat Jan 08 00:00:00 2000 PST + Sat Jan 08 00:00:00 2000 PST + Sat Jan 08 00:00:00 2000 PST + Sun Jan 09 00:00:00 2000 PST + Sun Jan 09 00:00:00 2000 PST + Sun Jan 09 00:00:00 2000 PST + Sun Jan 09 00:00:00 2000 PST + Mon Jan 10 00:00:00 2000 PST + Mon Jan 10 00:00:00 2000 PST + Mon Jan 10 00:00:00 2000 PST + Mon Jan 10 00:00:00 2000 PST + Tue Jan 11 00:00:00 2000 PST + Tue Jan 11 00:00:00 2000 PST + Tue Jan 11 00:00:00 2000 PST + Tue Jan 11 00:00:00 2000 PST + Wed Jan 12 00:00:00 2000 PST + Wed Jan 12 00:00:00 2000 PST + Wed Jan 12 00:00:00 2000 PST + Wed Jan 12 00:00:00 2000 PST + Thu Jan 13 00:00:00 2000 PST + Thu Jan 13 00:00:00 2000 PST + Thu Jan 13 00:00:00 2000 PST + Thu Jan 13 00:00:00 2000 PST + Fri Jan 14 00:00:00 2000 PST + Fri Jan 14 00:00:00 2000 PST + Fri Jan 14 00:00:00 2000 PST + Fri Jan 14 00:00:00 2000 PST + Sat Jan 15 00:00:00 2000 PST + Sat Jan 15 00:00:00 2000 PST + Sat Jan 15 00:00:00 2000 PST + Sat Jan 15 00:00:00 2000 PST + Sun Jan 16 00:00:00 2000 PST + Sun Jan 16 00:00:00 2000 PST + Sun Jan 16 00:00:00 2000 PST + Sun Jan 16 00:00:00 2000 PST + Mon Jan 17 00:00:00 2000 PST + Mon Jan 17 00:00:00 2000 PST + Mon Jan 17 00:00:00 2000 PST + Mon Jan 17 00:00:00 2000 PST + Tue Jan 18 00:00:00 2000 PST + Tue Jan 18 00:00:00 2000 PST + Tue Jan 18 00:00:00 2000 PST + Tue Jan 18 00:00:00 2000 PST + Wed Jan 19 00:00:00 2000 PST + Wed Jan 19 00:00:00 2000 PST + Wed Jan 19 00:00:00 2000 PST + Wed Jan 19 00:00:00 2000 PST + Thu Jan 20 00:00:00 2000 PST + Thu Jan 20 00:00:00 2000 PST + Thu Jan 20 00:00:00 2000 PST + Thu Jan 20 00:00:00 2000 PST + Fri Jan 21 00:00:00 2000 PST + Fri Jan 21 00:00:00 2000 PST + Fri Jan 21 00:00:00 2000 PST + Fri Jan 21 00:00:00 2000 PST + Sat Jan 22 00:00:00 2000 PST + Sat Jan 22 00:00:00 2000 PST + Sat Jan 22 00:00:00 2000 PST + Sat Jan 22 00:00:00 2000 PST + Sun Jan 23 00:00:00 2000 PST + Sun Jan 23 00:00:00 2000 PST + Sun Jan 23 00:00:00 2000 PST + Sun Jan 23 00:00:00 2000 PST + Mon Jan 24 00:00:00 2000 PST + Mon Jan 24 00:00:00 2000 PST + Mon Jan 24 00:00:00 2000 PST + Mon Jan 24 00:00:00 2000 PST + Tue Jan 25 00:00:00 2000 PST + Tue Jan 25 00:00:00 2000 PST + Tue Jan 25 00:00:00 2000 PST + Tue Jan 25 00:00:00 2000 PST + Wed Jan 26 00:00:00 2000 PST + Wed Jan 26 00:00:00 2000 PST + Wed Jan 26 00:00:00 2000 PST + Wed Jan 26 00:00:00 2000 PST + Thu Jan 27 00:00:00 2000 PST + Thu Jan 27 00:00:00 2000 PST + Thu Jan 27 00:00:00 2000 PST + Thu Jan 27 00:00:00 2000 PST + Fri Jan 28 00:00:00 2000 PST + Fri Jan 28 00:00:00 2000 PST + Fri Jan 28 00:00:00 2000 PST + Fri Jan 28 00:00:00 2000 PST + Sat Jan 29 00:00:00 2000 PST + Sat Jan 29 00:00:00 2000 PST + Sat Jan 29 00:00:00 2000 PST + Sat Jan 29 00:00:00 2000 PST + Sun Jan 30 00:00:00 2000 PST + Sun Jan 30 00:00:00 2000 PST + Sun Jan 30 00:00:00 2000 PST + Sun Jan 30 00:00:00 2000 PST + Mon Jan 31 00:00:00 2000 PST + Mon Jan 31 00:00:00 2000 PST + Mon Jan 31 00:00:00 2000 PST + Mon Jan 31 00:00:00 2000 PST + Tue Feb 01 00:00:00 2000 PST + Tue Feb 01 00:00:00 2000 PST + Tue Feb 01 00:00:00 2000 PST + Tue Feb 01 00:00:00 2000 PST +(128 rows) + +\ir include/plan_expand_hypertable_chunks_in_query.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +--we want to see how our logic excludes chunks +--and not how much work constraint_exclusion does +SET constraint_exclusion = 'off'; +:PREFIX SELECT * FROM hyper ORDER BY value; + QUERY PLAN +-------------------------------------------- + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + -> Seq Scan on _hyper_1_2_chunk + -> Seq Scan on _hyper_1_3_chunk + -> Seq Scan on _hyper_1_4_chunk + -> Seq Scan on _hyper_1_5_chunk + -> Seq Scan on _hyper_1_6_chunk + -> Seq Scan on _hyper_1_7_chunk + -> Seq Scan on _hyper_1_8_chunk + -> Seq Scan on _hyper_1_9_chunk + -> Seq Scan on _hyper_1_10_chunk + -> Seq Scan on _hyper_1_11_chunk + -> Seq Scan on _hyper_1_12_chunk + -> Seq Scan on _hyper_1_13_chunk + -> Seq Scan on _hyper_1_14_chunk + -> Seq Scan on _hyper_1_15_chunk + -> Seq Scan on _hyper_1_16_chunk + -> Seq Scan on _hyper_1_17_chunk + -> Seq Scan on _hyper_1_18_chunk + -> Seq Scan on _hyper_1_19_chunk + -> Seq Scan on _hyper_1_20_chunk + -> Seq Scan on _hyper_1_21_chunk + -> Seq Scan on _hyper_1_22_chunk + -> Seq Scan on _hyper_1_23_chunk + -> Seq Scan on _hyper_1_24_chunk + -> Seq Scan on _hyper_1_25_chunk + -> Seq Scan on _hyper_1_26_chunk + -> Seq Scan on _hyper_1_27_chunk + -> Seq Scan on _hyper_1_28_chunk + -> Seq Scan on _hyper_1_29_chunk + -> Seq Scan on _hyper_1_30_chunk + -> Seq Scan on _hyper_1_31_chunk + -> Seq Scan on _hyper_1_32_chunk + -> Seq Scan on _hyper_1_33_chunk + -> Seq Scan on _hyper_1_34_chunk + -> Seq Scan on _hyper_1_35_chunk + -> Seq Scan on _hyper_1_36_chunk + -> Seq Scan on _hyper_1_37_chunk + -> Seq Scan on _hyper_1_38_chunk + -> Seq Scan on _hyper_1_39_chunk + -> Seq Scan on _hyper_1_40_chunk + -> Seq Scan on _hyper_1_41_chunk + -> Seq Scan on _hyper_1_42_chunk + -> Seq Scan on _hyper_1_43_chunk + -> Seq Scan on _hyper_1_44_chunk + -> Seq Scan on _hyper_1_45_chunk + -> Seq Scan on _hyper_1_46_chunk + -> Seq Scan on _hyper_1_47_chunk + -> Seq Scan on _hyper_1_48_chunk + -> Seq Scan on _hyper_1_49_chunk + -> Seq Scan on _hyper_1_50_chunk + -> Seq Scan on _hyper_1_51_chunk + -> Seq Scan on _hyper_1_52_chunk + -> Seq Scan on _hyper_1_53_chunk + -> Seq Scan on _hyper_1_54_chunk + -> Seq Scan on _hyper_1_55_chunk + -> Seq Scan on _hyper_1_56_chunk + -> Seq Scan on _hyper_1_57_chunk + -> Seq Scan on _hyper_1_58_chunk + -> Seq Scan on _hyper_1_59_chunk + -> Seq Scan on _hyper_1_60_chunk + -> Seq Scan on _hyper_1_61_chunk + -> Seq Scan on _hyper_1_62_chunk + -> Seq Scan on _hyper_1_63_chunk + -> Seq Scan on _hyper_1_64_chunk + -> Seq Scan on _hyper_1_65_chunk + -> Seq Scan on _hyper_1_66_chunk + -> Seq Scan on _hyper_1_67_chunk + -> Seq Scan on _hyper_1_68_chunk + -> Seq Scan on _hyper_1_69_chunk + -> Seq Scan on _hyper_1_70_chunk + -> Seq Scan on _hyper_1_71_chunk + -> Seq Scan on _hyper_1_72_chunk + -> Seq Scan on _hyper_1_73_chunk + -> Seq Scan on _hyper_1_74_chunk + -> Seq Scan on _hyper_1_75_chunk + -> Seq Scan on _hyper_1_76_chunk + -> Seq Scan on _hyper_1_77_chunk + -> Seq Scan on _hyper_1_78_chunk + -> Seq Scan on _hyper_1_79_chunk + -> Seq Scan on _hyper_1_80_chunk + -> Seq Scan on _hyper_1_81_chunk + -> Seq Scan on _hyper_1_82_chunk + -> Seq Scan on _hyper_1_83_chunk + -> Seq Scan on _hyper_1_84_chunk + -> Seq Scan on _hyper_1_85_chunk + -> Seq Scan on _hyper_1_86_chunk + -> Seq Scan on _hyper_1_87_chunk + -> Seq Scan on _hyper_1_88_chunk + -> Seq Scan on _hyper_1_89_chunk + -> Seq Scan on _hyper_1_90_chunk + -> Seq Scan on _hyper_1_91_chunk + -> Seq Scan on _hyper_1_92_chunk + -> Seq Scan on _hyper_1_93_chunk + -> Seq Scan on _hyper_1_94_chunk + -> Seq Scan on _hyper_1_95_chunk + -> Seq Scan on _hyper_1_96_chunk + -> Seq Scan on _hyper_1_97_chunk + -> Seq Scan on _hyper_1_98_chunk + -> Seq Scan on _hyper_1_99_chunk + -> Seq Scan on _hyper_1_100_chunk + -> Seq Scan on _hyper_1_101_chunk + -> Seq Scan on _hyper_1_102_chunk +(105 rows) + +-- explicit chunk exclusion +:PREFIX SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(hyper, ARRAY[1,2]) ORDER BY value; + QUERY PLAN +------------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + -> Seq Scan on _hyper_1_2_chunk +(5 rows) + +:PREFIX SELECT * FROM (SELECT * FROM hyper h WHERE _timescaledb_internal.chunks_in(h, ARRAY[1,2,3])) T ORDER BY value; + QUERY PLAN +---------------------------------------------- + Sort + Sort Key: h_1.value + -> Append + -> Seq Scan on _hyper_1_1_chunk h_1 + -> Seq Scan on _hyper_1_2_chunk h_2 + -> Seq Scan on _hyper_1_3_chunk h_3 +(6 rows) + +:PREFIX SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(hyper, ARRAY[1,2,3]) AND time < 10 ORDER BY value; + QUERY PLAN +------------------------------------------ + Sort + Sort Key: _hyper_1_1_chunk.value + -> Append + -> Seq Scan on _hyper_1_1_chunk + Filter: ("time" < 10) + -> Seq Scan on _hyper_1_2_chunk + Filter: ("time" < 10) + -> Seq Scan on _hyper_1_3_chunk + Filter: ("time" < 10) +(9 rows) + +:PREFIX SELECT * FROM hyper_ts WHERE device_id = 'dev1' AND time < to_timestamp(10) AND _timescaledb_internal.chunks_in(hyper_ts, ARRAY[116]) ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: _hyper_3_116_chunk.value + -> Seq Scan on _hyper_3_116_chunk + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) +(4 rows) + +:PREFIX SELECT * FROM hyper_ts h JOIN tag on (h.tag_id = tag.id ) WHERE _timescaledb_internal.chunks_in(h, ARRAY[116]) AND time < to_timestamp(10) AND device_id = 'dev1' ORDER BY value; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: h.value + -> Merge Join + Merge Cond: (tag.id = h.tag_id) + -> Index Scan using tag_pkey on tag + -> Sort + Sort Key: h.tag_id + -> Seq Scan on _hyper_3_116_chunk h + Filter: (("time" < 'Wed Dec 31 16:00:10 1969 PST'::timestamp with time zone) AND (device_id = 'dev1'::text)) +(9 rows) + +:PREFIX SELECT * FROM hyper_w_space h1 JOIN hyper_ts h2 ON h1.device_id=h2.device_id WHERE _timescaledb_internal.chunks_in(h1, ARRAY[104,105]) AND _timescaledb_internal.chunks_in(h2, ARRAY[116,117]) ORDER BY h1.value; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: h1_1.value + -> Hash Join + Hash Cond: (h2_1.device_id = h1_1.device_id) + -> Append + -> Seq Scan on _hyper_3_116_chunk h2_1 + -> Seq Scan on _hyper_3_117_chunk h2_2 + -> Hash + -> Append + -> Seq Scan on _hyper_2_104_chunk h1_1 + -> Seq Scan on _hyper_2_105_chunk h1_2 +(11 rows) + +:PREFIX SELECT * FROM hyper_w_space h1 JOIN hyper_ts h2 ON h1.device_id=h2.device_id AND _timescaledb_internal.chunks_in(h2, ARRAY[116,117]) WHERE _timescaledb_internal.chunks_in(h1, ARRAY[104,105]) ORDER BY h1.value; + QUERY PLAN +------------------------------------------------------------- + Sort + Sort Key: h1_1.value + -> Hash Join + Hash Cond: (h2_1.device_id = h1_1.device_id) + -> Append + -> Seq Scan on _hyper_3_116_chunk h2_1 + -> Seq Scan on _hyper_3_117_chunk h2_2 + -> Hash + -> Append + -> Seq Scan on _hyper_2_104_chunk h1_1 + -> Seq Scan on _hyper_2_105_chunk h1_2 +(11 rows) + +:PREFIX SELECT * FROM hyper h1, hyper h2 WHERE _timescaledb_internal.chunks_in(h1, ARRAY[1,2]) AND _timescaledb_internal.chunks_in(h2, ARRAY[2,3]); + QUERY PLAN +----------------------------------------------------- + Nested Loop + -> Append + -> Seq Scan on _hyper_1_1_chunk h1_1 + -> Seq Scan on _hyper_1_2_chunk h1_2 + -> Materialize + -> Append + -> Seq Scan on _hyper_1_2_chunk h2_1 + -> Seq Scan on _hyper_1_3_chunk h2_2 +(8 rows) + +SET enable_seqscan=false; +-- Should perform index-only scan. Since we pass whole row into the function it might block planner from using index-only scan. +-- But since we'll remove the function from the query tree before planner decision it shouldn't affect index-only decision. +:PREFIX SELECT time FROM hyper WHERE time=0 AND _timescaledb_internal.chunks_in(hyper, ARRAY[1]); + QUERY PLAN +--------------------------------------------------------------------------- + Index Only Scan using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk + Index Cond: ("time" = 0) +(2 rows) + +:PREFIX SELECT first(value, time) FROM hyper h WHERE _timescaledb_internal.chunks_in(h, ARRAY[1]); + QUERY PLAN +----------------------------------------------------------------------------------------------- + Result + InitPlan 1 (returns $0) + -> Limit + -> Index Scan Backward using _hyper_1_1_chunk_hyper_time_idx on _hyper_1_1_chunk h + Index Cond: ("time" IS NOT NULL) +(5 rows) + +\set ON_ERROR_STOP 0 +SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(hyper, ARRAY[1,2]) AND _timescaledb_internal.chunks_in(hyper, ARRAY[2,3]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:26: ERROR: illegal invocation of chunks_in function +SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(2, ARRAY[1]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:27: ERROR: function _timescaledb_internal.chunks_in(integer, integer[]) does not exist at character 27 +SELECT * FROM hyper WHERE time < 10 OR _timescaledb_internal.chunks_in(hyper, ARRAY[1,2]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:28: ERROR: illegal invocation of chunks_in function +SELECT _timescaledb_internal.chunks_in(hyper, ARRAY[1,2]) FROM hyper; +psql:include/plan_expand_hypertable_chunks_in_query.sql:29: ERROR: illegal invocation of chunks_in function +-- non existing chunk id +SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(hyper, ARRAY[123456789]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:31: ERROR: chunk id 123456789 not found +-- chunk that belongs to another hypertable +SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(hyper, ARRAY[104]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:33: ERROR: chunk id 104 does not belong to hypertable "hyper" +-- passing wrong row ref +SELECT * FROM hyper WHERE _timescaledb_internal.chunks_in(ROW(1,2), ARRAY[104]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:35: ERROR: first parameter for chunks_in function needs to be record +-- passing func as chunk id +SELECT * FROM hyper h WHERE _timescaledb_internal.chunks_in(h, array_append(ARRAY[1],current_setting('server_version_num')::int)); +psql:include/plan_expand_hypertable_chunks_in_query.sql:37: ERROR: second argument to chunk_in should contain only integer consts +-- NULL chunk IDs not allowed in chunk array +SELECT * FROM hyper h WHERE _timescaledb_internal.chunks_in(h, ARRAY[NULL::int]); +psql:include/plan_expand_hypertable_chunks_in_query.sql:39: ERROR: chunk id can't be NULL +\set ON_ERROR_STOP 1 +-- chunks_in is STRICT function and for NULL arguments a null result is returned +SELECT * FROM hyper h WHERE _timescaledb_internal.chunks_in(h, NULL); + value | time +-------+------ +(0 rows) + +\set ECHO errors +RESET timescaledb.enable_optimizations; +CREATE TABLE test (a int, time timestamptz NOT NULL); +SELECT create_hypertable('public.test', 'time'); + create_hypertable +-------------------- + (15,public,test,t) +(1 row) + +INSERT INTO test SELECT i, '2020-04-01'::date-10-i from generate_series(1,20) i; +CREATE OR REPLACE FUNCTION test_f(_ts timestamptz) +RETURNS SETOF test LANGUAGE SQL STABLE PARALLEL SAFE +AS $f$ + SELECT DISTINCT ON (a) * FROM test WHERE time >= _ts ORDER BY a, time DESC +$f$; +EXPLAIN (costs off) SELECT * FROM test_f(now()); + QUERY PLAN +------------------------------------------------- + Unique + -> Sort + Sort Key: test.a, test."time" DESC + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 4 +(5 rows) + +EXPLAIN (costs off) SELECT * FROM test_f(now()); + QUERY PLAN +------------------------------------------------- + Unique + -> Sort + Sort Key: test.a, test."time" DESC + -> Custom Scan (ChunkAppend) on test + Chunks excluded during startup: 4 +(5 rows) + +--TEST END-- diff --git a/test/expected/plan_hashagg-13.out b/test/expected/plan_hashagg-13.out new file mode 100644 index 000000000..f746bb912 --- /dev/null +++ b/test/expected/plan_hashagg-13.out @@ -0,0 +1,329 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set PREFIX 'EXPLAIN (costs off) ' +\ir include/plan_hashagg_load.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE metric (id SERIAL PRIMARY KEY, value INT); +CREATE TABLE hyper(time TIMESTAMP NOT NULL, time_int BIGINT, time_broken DATE, metricid int, value double precision); +CREATE TABLE regular(time TIMESTAMP NOT NULL, time_int BIGINT, time_date DATE, metricid int, value double precision); +SELECT create_hypertable('hyper', 'time', chunk_time_interval => interval '20 day', create_default_indexes=>FALSE); + create_hypertable +-------------------- + (1,public,hyper,t) +(1 row) + +ALTER TABLE hyper +DROP COLUMN time_broken, +ADD COLUMN time_date DATE; +INSERT INTO metric(value) SELECT random()*100 FROM generate_series(0,10); +INSERT INTO hyper SELECT t, EXTRACT(EPOCH FROM t), (EXTRACT(EPOCH FROM t)::int % 10)+1, 1.0, t::date FROM generate_series('2001-01-01', '2001-01-10', INTERVAL '1 second') t; +INSERT INTO regular(time, time_int, time_date, metricid, value) + SELECT t, EXTRACT(EPOCH FROM t), t::date, (EXTRACT(EPOCH FROM t)::int % 10) + 1, 1.0 FROM generate_series('2001-01-01', '2001-01-02', INTERVAL '1 second') t; +--test some queries before analyze; +EXPLAIN (costs off) SELECT time_bucket('1 minute', time) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, _hyper_1_1_chunk."time")) + -> Gather Merge + Workers Planned: 2 + -> Partial GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, _hyper_1_1_chunk."time")) + -> Sort + Sort Key: (time_bucket('@ 1 min'::interval, _hyper_1_1_chunk."time")) DESC + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +EXPLAIN (costs off) SELECT date_trunc('minute', time) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (date_trunc('minute'::text, _hyper_1_1_chunk."time")) + -> Gather Merge + Workers Planned: 2 + -> Partial GroupAggregate + Group Key: (date_trunc('minute'::text, _hyper_1_1_chunk."time")) + -> Sort + Sort Key: (date_trunc('minute'::text, _hyper_1_1_chunk."time")) DESC + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +-- Test partitioning function on an open (time) dimension +CREATE OR REPLACE FUNCTION unix_to_timestamp(unixtime float8) + RETURNS TIMESTAMPTZ LANGUAGE SQL IMMUTABLE AS +$BODY$ + SELECT to_timestamp(unixtime); +$BODY$; +CREATE TABLE hyper_timefunc(time float8 NOT NULL, metricid int, VALUE double precision, time_date DATE); +SELECT create_hypertable('hyper_timefunc', 'time', chunk_time_interval => interval '20 day', create_default_indexes=>FALSE, time_partitioning_func => 'unix_to_timestamp'); + create_hypertable +----------------------------- + (2,public,hyper_timefunc,t) +(1 row) + +INSERT INTO hyper_timefunc SELECT time_int, metricid, VALUE, time_date FROM hyper; +ANALYZE metric; +ANALYZE hyper; +ANALYZE regular; +ANALYZE hyper_timefunc; +\ir include/plan_hashagg_query.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +:PREFIX SELECT time_bucket('1 minute', time) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (time_bucket('@ 1 min'::interval, _hyper_1_1_chunk."time")) DESC + -> HashAggregate + Group Key: time_bucket('@ 1 min'::interval, _hyper_1_1_chunk."time") + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +:PREFIX SELECT time_bucket('1 hour', time) AS MetricMinuteTs, metricid, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs, metricid +ORDER BY MetricMinuteTs DESC, metricid; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (time_bucket('@ 1 hour'::interval, _hyper_1_1_chunk."time")) DESC, _hyper_1_1_chunk.metricid + -> HashAggregate + Group Key: time_bucket('@ 1 hour'::interval, _hyper_1_1_chunk."time"), _hyper_1_1_chunk.metricid + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +--should be too many groups will not hashaggregate +:PREFIX SELECT time_bucket('1 second', time) AS MetricMinuteTs, metricid, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs, metricid +ORDER BY MetricMinuteTs DESC, metricid; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (time_bucket('@ 1 sec'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.metricid + -> Gather Merge + Workers Planned: 2 + -> Partial GroupAggregate + Group Key: (time_bucket('@ 1 sec'::interval, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.metricid + -> Sort + Sort Key: (time_bucket('@ 1 sec'::interval, _hyper_1_1_chunk."time")) DESC, _hyper_1_1_chunk.metricid + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +:PREFIX SELECT time_bucket('1 minute', time, INTERVAL '30 seconds') AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: ((time_bucket('@ 1 min'::interval, (_hyper_1_1_chunk."time" - '@ 30 secs'::interval)) + '@ 30 secs'::interval)) DESC + -> HashAggregate + Group Key: (time_bucket('@ 1 min'::interval, (_hyper_1_1_chunk."time" - '@ 30 secs'::interval)) + '@ 30 secs'::interval) + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +:PREFIX SELECT time_bucket(60, time_int) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (time_bucket('60'::bigint, _hyper_1_1_chunk.time_int)) DESC + -> HashAggregate + Group Key: time_bucket('60'::bigint, _hyper_1_1_chunk.time_int) + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +:PREFIX SELECT time_bucket(60, time_int, 10) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (time_bucket('60'::bigint, _hyper_1_1_chunk.time_int, '10'::bigint)) DESC + -> HashAggregate + Group Key: time_bucket('60'::bigint, _hyper_1_1_chunk.time_int, '10'::bigint) + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +:PREFIX SELECT time_bucket('1 day', time_date) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (time_bucket('@ 1 day'::interval, _hyper_1_1_chunk.time_date)) + -> Gather Merge + Workers Planned: 2 + -> Sort + Sort Key: (time_bucket('@ 1 day'::interval, _hyper_1_1_chunk.time_date)) DESC + -> Partial HashAggregate + Group Key: time_bucket('@ 1 day'::interval, _hyper_1_1_chunk.time_date) + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +:PREFIX SELECT date_trunc('minute', time) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (date_trunc('minute'::text, _hyper_1_1_chunk."time")) DESC + -> HashAggregate + Group Key: date_trunc('minute'::text, _hyper_1_1_chunk."time") + -> Result + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(7 rows) + +\set ON_ERROR_STOP 0 +--can't optimize invalid time unit +:PREFIX SELECT date_trunc('invalid', time) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (date_trunc('invalid'::text, _hyper_1_1_chunk."time")) + -> Gather Merge + Workers Planned: 2 + -> Partial GroupAggregate + Group Key: (date_trunc('invalid'::text, _hyper_1_1_chunk."time")) + -> Sort + Sort Key: (date_trunc('invalid'::text, _hyper_1_1_chunk."time")) DESC + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +\set ON_ERROR_STOP 1 +:PREFIX SELECT date_trunc('day', time_date) AS MetricMinuteTs, AVG(value) as avg +FROM hyper +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize GroupAggregate + Group Key: (date_trunc('day'::text, (_hyper_1_1_chunk.time_date)::timestamp with time zone)) + -> Gather Merge + Workers Planned: 2 + -> Sort + Sort Key: (date_trunc('day'::text, (_hyper_1_1_chunk.time_date)::timestamp with time zone)) DESC + -> Partial HashAggregate + Group Key: date_trunc('day'::text, (_hyper_1_1_chunk.time_date)::timestamp with time zone) + -> Result + -> Parallel Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) +(11 rows) + +--joins +--with hypertable, optimize +:PREFIX SELECT time_bucket(3600, time_int, 10) AS MetricMinuteTs, metric.value, AVG(hyper.value) as avg +FROM hyper +JOIN metric ON (hyper.metricid = metric.id) +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs, metric.id +ORDER BY MetricMinuteTs DESC, metric.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: (time_bucket('3600'::bigint, _hyper_1_1_chunk.time_int, '10'::bigint)) DESC, metric.id + -> HashAggregate + Group Key: time_bucket('3600'::bigint, _hyper_1_1_chunk.time_int, '10'::bigint), metric.id + -> Hash Join + Hash Cond: (_hyper_1_1_chunk.metricid = metric.id) + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) + -> Hash + -> Seq Scan on metric +(10 rows) + +--no hypertable involved, no optimization +:PREFIX SELECT time_bucket(3600, time_int, 10) AS MetricMinuteTs, metric.value, AVG(regular.value) as avg +FROM regular +JOIN metric ON (regular.metricid = metric.id) +WHERE time >= '2001-01-04T00:00:00' AND time <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs, metric.id +ORDER BY MetricMinuteTs DESC, metric.id; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Group Key: (time_bucket('3600'::bigint, regular.time_int, '10'::bigint)), metric.id + -> Sort + Sort Key: (time_bucket('3600'::bigint, regular.time_int, '10'::bigint)) DESC, metric.id + -> Nested Loop + Join Filter: (regular.metricid = metric.id) + -> Seq Scan on regular + Filter: (("time" >= 'Thu Jan 04 00:00:00 2001'::timestamp without time zone) AND ("time" <= 'Fri Jan 05 01:00:00 2001'::timestamp without time zone)) + -> Seq Scan on metric +(9 rows) + +-- Try with time partitioning function. Currently not optimized for hash aggregates +:PREFIX SELECT time_bucket('1 minute', unix_to_timestamp(time)) AS MetricMinuteTs, AVG(value) as avg +FROM hyper_timefunc +WHERE unix_to_timestamp(time) >= '2001-01-04T00:00:00' AND unix_to_timestamp(time) <= '2001-01-05T01:00:00' +GROUP BY MetricMinuteTs +ORDER BY MetricMinuteTs DESC; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, to_timestamp(_hyper_2_2_chunk."time"))) + -> Sort + Sort Key: (time_bucket('@ 1 min'::interval, to_timestamp(_hyper_2_2_chunk."time"))) DESC + -> Result + -> Seq Scan on _hyper_2_2_chunk + Filter: ((to_timestamp("time") >= 'Thu Jan 04 00:00:00 2001 PST'::timestamp with time zone) AND (to_timestamp("time") <= 'Fri Jan 05 01:00:00 2001 PST'::timestamp with time zone)) +(7 rows) + +\set ECHO none +psql:include/plan_hashagg_query.sql:60: ERROR: timestamp units "invalid" not recognized +psql:include/plan_hashagg_query.sql:60: ERROR: timestamp units "invalid" not recognized diff --git a/test/expected/query-13.out b/test/expected/query-13.out new file mode 100644 index 000000000..270240926 --- /dev/null +++ b/test/expected/query-13.out @@ -0,0 +1,408 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set TEST_BASE_NAME query +SELECT format('include/%s_load.sql', :'TEST_BASE_NAME') as "TEST_LOAD_NAME", + format('include/%s_query.sql', :'TEST_BASE_NAME') as "TEST_QUERY_NAME", + format('%s/results/%s_results_optimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_OPTIMIZED", + format('%s/results/%s_results_unoptimized.out', :'TEST_OUTPUT_DIR', :'TEST_BASE_NAME') as "TEST_RESULTS_UNOPTIMIZED" +\gset +SELECT format('\! diff -u --label "Unoptimized result" --label "Optimized result" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD" +\gset +\set PREFIX 'EXPLAIN (costs OFF)' +\ir :TEST_LOAD_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE PUBLIC.hyper_1 ( + time TIMESTAMP NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE INDEX "time_plain" ON PUBLIC.hyper_1 (time DESC, series_0); +SELECT * FROM create_hypertable('"public"."hyper_1"'::regclass, 'time'::name, number_partitions => 1, create_default_indexes=>false); + hypertable_id | schema_name | table_name | created +---------------+-------------+------------+--------- + 1 | public | hyper_1 | t +(1 row) + +INSERT INTO hyper_1 SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO hyper_1 SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +CREATE TABLE PUBLIC.hyper_1_tz ( + time TIMESTAMPTZ NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE INDEX "time_plain_tz" ON PUBLIC.hyper_1_tz (time DESC, series_0); +SELECT * FROM create_hypertable('"public"."hyper_1_tz"'::regclass, 'time'::name, number_partitions => 1, create_default_indexes=>false); + hypertable_id | schema_name | table_name | created +---------------+-------------+------------+--------- + 2 | public | hyper_1_tz | t +(1 row) + +INSERT INTO hyper_1_tz SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO hyper_1_tz SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +CREATE TABLE PUBLIC.hyper_1_int ( + time int NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE INDEX "time_plain_int" ON PUBLIC.hyper_1_int (time DESC, series_0); +SELECT * FROM create_hypertable('"public"."hyper_1_int"'::regclass, 'time'::name, number_partitions => 1, chunk_time_interval=>10000, create_default_indexes=>FALSE); + hypertable_id | schema_name | table_name | created +---------------+-------------+-------------+--------- + 3 | public | hyper_1_int | t +(1 row) + +INSERT INTO hyper_1_int SELECT ser, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO hyper_1_int SELECT ser, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +CREATE TABLE PUBLIC.hyper_1_date ( + time date NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE INDEX "time_plain_date" ON PUBLIC.hyper_1_date (time DESC, series_0); +SELECT * FROM create_hypertable('"public"."hyper_1_date"'::regclass, 'time'::name, number_partitions => 1, chunk_time_interval=>86400000000, create_default_indexes=>FALSE); + hypertable_id | schema_name | table_name | created +---------------+-------------+--------------+--------- + 4 | public | hyper_1_date | t +(1 row) + +INSERT INTO hyper_1_date SELECT to_timestamp(ser)::date, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO hyper_1_date SELECT to_timestamp(ser)::date, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +--below needed to create enough unique dates to trigger an index scan +INSERT INTO hyper_1_date SELECT to_timestamp(ser*100)::date, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +CREATE TABLE PUBLIC.plain_table ( + time TIMESTAMPTZ NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE INDEX "time_plain_plain_table" ON PUBLIC.plain_table (time DESC, series_0); +INSERT INTO plain_table SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO plain_table SELECT to_timestamp(ser), ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +-- Table with a time partitioning function +CREATE TABLE PUBLIC.hyper_timefunc ( + time float8 NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL +); +CREATE OR REPLACE FUNCTION unix_to_timestamp(unixtime float8) + RETURNS TIMESTAMPTZ LANGUAGE SQL IMMUTABLE AS +$BODY$ + SELECT to_timestamp(unixtime); +$BODY$; +CREATE INDEX "time_plain_timefunc" ON PUBLIC.hyper_timefunc (to_timestamp(time) DESC, series_0); +SELECT * FROM create_hypertable('"public"."hyper_timefunc"'::regclass, 'time'::name, number_partitions => 1, create_default_indexes=>false, time_partitioning_func => 'unix_to_timestamp'); + hypertable_id | schema_name | table_name | created +---------------+-------------+----------------+--------- + 5 | public | hyper_timefunc | t +(1 row) + +INSERT INTO hyper_timefunc SELECT ser, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(0,10000) ser; +INSERT INTO hyper_timefunc SELECT ser, ser, ser+10000, sqrt(ser::numeric) FROM generate_series(10001,20000) ser; +ANALYZE plain_table; +ANALYZE hyper_timefunc; +ANALYZE hyper_1; +ANALYZE hyper_1_tz; +ANALYZE hyper_1_int; +ANALYZE hyper_1_date; +\ir :TEST_QUERY_NAME +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +SHOW timescaledb.enable_optimizations; + timescaledb.enable_optimizations +---------------------------------- + on +(1 row) + +--non-aggregates use MergeAppend in both optimized and non-optimized +:PREFIX SELECT * FROM hyper_1 ORDER BY "time" DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------ + Limit + -> Custom Scan (ChunkAppend) on hyper_1 + Order: hyper_1."time" DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(4 rows) + +:PREFIX SELECT * FROM hyper_timefunc ORDER BY unix_to_timestamp("time") DESC limit 2; + QUERY PLAN +----------------------------------------------------------------------------------- + Limit + -> Index Scan using _hyper_5_19_chunk_time_plain_timefunc on _hyper_5_19_chunk +(2 rows) + +--Aggregates use MergeAppend only in optimized +:PREFIX SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: (date_trunc('minute'::text, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: date_trunc('minute'::text, hyper_1."time") DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(6 rows) + +:PREFIX SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1_date GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (date_trunc('minute'::text, (_hyper_4_6_chunk."time")::timestamp with time zone)) + -> Result + -> Merge Append + Sort Key: (date_trunc('minute'::text, (_hyper_4_6_chunk."time")::timestamp with time zone)) DESC + -> Index Scan using _hyper_4_6_chunk_time_plain_date on _hyper_4_6_chunk + -> Index Scan using _hyper_4_7_chunk_time_plain_date on _hyper_4_7_chunk + -> Index Scan using _hyper_4_8_chunk_time_plain_date on _hyper_4_8_chunk + -> Index Scan using _hyper_4_9_chunk_time_plain_date on _hyper_4_9_chunk + -> Index Scan using _hyper_4_10_chunk_time_plain_date on _hyper_4_10_chunk + -> Index Scan using _hyper_4_11_chunk_time_plain_date on _hyper_4_11_chunk + -> Index Scan using _hyper_4_12_chunk_time_plain_date on _hyper_4_12_chunk + -> Index Scan using _hyper_4_13_chunk_time_plain_date on _hyper_4_13_chunk + -> Index Scan using _hyper_4_14_chunk_time_plain_date on _hyper_4_14_chunk + -> Index Scan using _hyper_4_15_chunk_time_plain_date on _hyper_4_15_chunk + -> Index Scan using _hyper_4_16_chunk_time_plain_date on _hyper_4_16_chunk + -> Index Scan using _hyper_4_17_chunk_time_plain_date on _hyper_4_17_chunk + -> Index Scan using _hyper_4_18_chunk_time_plain_date on _hyper_4_18_chunk +(19 rows) + +--the minute and second results should be diff +:PREFIX SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: (date_trunc('minute'::text, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: date_trunc('minute'::text, hyper_1."time") DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(6 rows) + +:PREFIX SELECT date_trunc('second', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: (date_trunc('second'::text, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: date_trunc('second'::text, hyper_1."time") DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(6 rows) + +--test that when index on time used by constraint, still works correctly +:PREFIX +SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) +FROM hyper_1 +WHERE time < to_timestamp(900) +GROUP BY t +ORDER BY t DESC +LIMIT 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: (date_trunc('minute'::text, hyper_1."time")) DESC + -> HashAggregate + Group Key: date_trunc('minute'::text, hyper_1."time") + -> Custom Scan (ChunkAppend) on hyper_1 + Chunks excluded during startup: 0 + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk + Index Cond: ("time" < 'Wed Dec 31 16:15:00 1969 PST'::timestamp with time zone) +(9 rows) + +--test on table with time partitioning function. Currently not +--optimized to use index for ordering since the index is an expression +--on time (e.g., timefunc(time)), and we currently don't handle that +--case. +:PREFIX +SELECT date_trunc('minute', to_timestamp(time)) t, avg(series_0), min(series_1), avg(series_2) +FROM hyper_timefunc +WHERE to_timestamp(time) < to_timestamp(900) +GROUP BY t +ORDER BY t DESC +LIMIT 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: (date_trunc('minute'::text, to_timestamp(_hyper_5_19_chunk."time"))) DESC + -> HashAggregate + Group Key: date_trunc('minute'::text, to_timestamp(_hyper_5_19_chunk."time")) + -> Result + -> Index Scan using _hyper_5_19_chunk_time_plain_timefunc on _hyper_5_19_chunk + Index Cond: (to_timestamp("time") < 'Wed Dec 31 16:15:00 1969 PST'::timestamp with time zone) +(8 rows) + +BEGIN; + --test that still works with an expression index on data_trunc. + DROP INDEX "time_plain"; + CREATE INDEX "time_trunc" ON PUBLIC.hyper_1 (date_trunc('minute', time)); + ANALYZE hyper_1; + :PREFIX SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (date_trunc('minute'::text, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: date_trunc('minute'::text, hyper_1."time") DESC + -> Index Scan Backward using _hyper_1_1_chunk_time_trunc on _hyper_1_1_chunk +(6 rows) + + --test that works with both indexes + CREATE INDEX "time_plain" ON PUBLIC.hyper_1 (time DESC, series_0); + ANALYZE hyper_1; + :PREFIX SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +--------------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (date_trunc('minute'::text, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: date_trunc('minute'::text, hyper_1."time") DESC + -> Index Scan Backward using _hyper_1_1_chunk_time_trunc on _hyper_1_1_chunk +(6 rows) + + :PREFIX SELECT time_bucket('1 minute', time) t, avg(series_0), min(series_1), trunc(avg(series_2)::numeric, 5) + FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, hyper_1."time")) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: time_bucket('@ 1 min'::interval, hyper_1."time") DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(6 rows) + + :PREFIX SELECT time_bucket('1 minute', time, INTERVAL '30 seconds') t, avg(series_0), min(series_1), trunc(avg(series_2)::numeric,5) + FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: ((time_bucket('@ 1 min'::interval, (_hyper_1_1_chunk."time" - '@ 30 secs'::interval)) + '@ 30 secs'::interval)) + -> Result + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(5 rows) + + :PREFIX SELECT time_bucket('1 minute', time - INTERVAL '30 seconds') t, avg(series_0), min(series_1), trunc(avg(series_2)::numeric,5) + FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, (hyper_1."time" - '@ 30 secs'::interval))) + -> Custom Scan (ChunkAppend) on hyper_1 + Order: time_bucket('@ 1 min'::interval, (hyper_1."time" - '@ 30 secs'::interval)) DESC + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(6 rows) + + :PREFIX SELECT time_bucket('1 minute', time - INTERVAL '30 seconds') + INTERVAL '30 seconds' t, avg(series_0), min(series_1), trunc(avg(series_2)::numeric,5) + FROM hyper_1 GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------ + Limit + -> GroupAggregate + Group Key: ((time_bucket('@ 1 min'::interval, (_hyper_1_1_chunk."time" - '@ 30 secs'::interval)) + '@ 30 secs'::interval)) + -> Result + -> Index Scan using _hyper_1_1_chunk_time_plain on _hyper_1_1_chunk +(5 rows) + + :PREFIX SELECT time_bucket('1 minute', time) t, avg(series_0), min(series_1), avg(series_2) + FROM hyper_1_tz GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +--------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, hyper_1_tz."time")) + -> Custom Scan (ChunkAppend) on hyper_1_tz + Order: time_bucket('@ 1 min'::interval, hyper_1_tz."time") DESC + -> Index Scan using _hyper_2_2_chunk_time_plain_tz on _hyper_2_2_chunk +(6 rows) + + :PREFIX SELECT time_bucket('1 minute', time::timestamp) t, avg(series_0), min(series_1), avg(series_2) + FROM hyper_1_tz GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (time_bucket('@ 1 min'::interval, (_hyper_2_2_chunk."time")::timestamp without time zone)) + -> Result + -> Index Scan using _hyper_2_2_chunk_time_plain_tz on _hyper_2_2_chunk +(5 rows) + + :PREFIX SELECT time_bucket(10, time) t, avg(series_0), min(series_1), avg(series_2) + FROM hyper_1_int GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +---------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (time_bucket(10, hyper_1_int."time")) + -> Custom Scan (ChunkAppend) on hyper_1_int + Order: time_bucket(10, hyper_1_int."time") DESC + -> Index Scan using _hyper_3_5_chunk_time_plain_int on _hyper_3_5_chunk + -> Index Scan using _hyper_3_4_chunk_time_plain_int on _hyper_3_4_chunk + -> Index Scan using _hyper_3_3_chunk_time_plain_int on _hyper_3_3_chunk +(8 rows) + + :PREFIX SELECT time_bucket(10, time, 2) t, avg(series_0), min(series_1), avg(series_2) + FROM hyper_1_int GROUP BY t ORDER BY t DESC limit 2; + QUERY PLAN +---------------------------------------------------------------------------------------- + Limit + -> GroupAggregate + Group Key: (time_bucket(10, hyper_1_int."time", 2)) + -> Custom Scan (ChunkAppend) on hyper_1_int + Order: time_bucket(10, hyper_1_int."time", 2) DESC + -> Index Scan using _hyper_3_5_chunk_time_plain_int on _hyper_3_5_chunk + -> Index Scan using _hyper_3_4_chunk_time_plain_int on _hyper_3_4_chunk + -> Index Scan using _hyper_3_3_chunk_time_plain_int on _hyper_3_3_chunk +(8 rows) + +ROLLBACK; +-- sort order optimization should not be applied to non-hypertables +:PREFIX +SELECT date_trunc('minute', time) t, avg(series_0), min(series_1), avg(series_2) +FROM plain_table +WHERE time < to_timestamp(900) +GROUP BY t +ORDER BY t DESC +LIMIT 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Limit + -> Sort + Sort Key: (date_trunc('minute'::text, "time")) DESC + -> HashAggregate + Group Key: date_trunc('minute'::text, "time") + -> Index Scan using time_plain_plain_table on plain_table + Index Cond: ("time" < 'Wed Dec 31 16:15:00 1969 PST'::timestamp with time zone) +(7 rows) + +--generate the results into two different files +\set ECHO errors +--- Unoptimized result ++++ Optimized result +@@ -1,6 +1,6 @@ + timescaledb.enable_optimizations + ---------------------------------- +- off ++ on + (1 row) + + time | series_0 | series_1 | series_2 + ?column? +---------- + Done +(1 row) + diff --git a/test/expected/sort_optimization-13.out b/test/expected/sort_optimization-13.out new file mode 100644 index 000000000..5e9e04927 --- /dev/null +++ b/test/expected/sort_optimization-13.out @@ -0,0 +1,73 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\set PREFIX 'EXPLAIN (COSTS OFF) ' +CREATE TABLE order_test(time int NOT NULL, device_id int, value float); +CREATE INDEX ON order_test(time,device_id); +CREATE INDEX ON order_test(device_id,time); +SELECT create_hypertable('order_test','time',chunk_time_interval:=1000); + create_hypertable +------------------------- + (1,public,order_test,t) +(1 row) + +INSERT INTO order_test SELECT 0,10,0.5; +INSERT INTO order_test SELECT 1,9,0.5; +INSERT INTO order_test SELECT 2,8,0.5; +-- we want to see here that index scans are possible for the chosen expressions +-- so we disable seqscan so we dont need to worry about other factors which would +-- make PostgreSQL prefer seqscan over index scan +SET enable_seqscan TO off; +-- test sort optimization with single member order by +SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 1; + time_bucket | device_id | value +-------------+-----------+------- + 0 | 10 | 0.5 + 0 | 9 | 0.5 + 0 | 8 | 0.5 +(3 rows) + +-- should use index scan +:PREFIX SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 1; + QUERY PLAN +------------------------------------------------------------------------------------------ + Result + -> Index Scan Backward using _hyper_1_1_chunk_order_test_time_idx on _hyper_1_1_chunk +(2 rows) + +-- test sort optimization with ordering by multiple columns and time_bucket not last +SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 1,2; + time_bucket | device_id | value +-------------+-----------+------- + 0 | 8 | 0.5 + 0 | 9 | 0.5 + 0 | 10 | 0.5 +(3 rows) + +-- must not use index scan +:PREFIX SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 1,2; + QUERY PLAN +------------------------------------------------------------------------------------ + Sort + Sort Key: (time_bucket(10, _hyper_1_1_chunk."time")), _hyper_1_1_chunk.device_id + -> Result + -> Seq Scan on _hyper_1_1_chunk +(4 rows) + +-- test sort optimization with ordering by multiple columns and time_bucket as last member +SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 2,1; + time_bucket | device_id | value +-------------+-----------+------- + 0 | 8 | 0.5 + 0 | 9 | 0.5 + 0 | 10 | 0.5 +(3 rows) + +-- should use index scan +:PREFIX SELECT time_bucket(10,time),device_id,value FROM order_test ORDER BY 2,1; + QUERY PLAN +------------------------------------------------------------------------------------------- + Result + -> Index Scan using _hyper_1_1_chunk_order_test_device_id_time_idx on _hyper_1_1_chunk +(2 rows) + diff --git a/test/expected/sql_query-13.out b/test/expected/sql_query-13.out new file mode 100644 index 000000000..19356a99a --- /dev/null +++ b/test/expected/sql_query-13.out @@ -0,0 +1,279 @@ +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +\o /dev/null +\ir include/insert_two_partitions.sql +-- This file and its contents are licensed under the Apache License 2.0. +-- Please see the included NOTICE for copyright information and +-- LICENSE-APACHE for a copy of the license. +CREATE TABLE PUBLIC."two_Partitions" ( + "timeCustom" BIGINT NOT NULL, + device_id TEXT NOT NULL, + series_0 DOUBLE PRECISION NULL, + series_1 DOUBLE PRECISION NULL, + series_2 DOUBLE PRECISION NULL, + series_bool BOOLEAN NULL +); +CREATE INDEX ON PUBLIC."two_Partitions" (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_1) WHERE series_1 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL; +CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, device_id); +SELECT * FROM create_hypertable('"public"."two_Partitions"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2, chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month')); +\set QUIET off +BEGIN; +\COPY public."two_Partitions" FROM 'data/ds1_dev1_1.tsv' NULL AS ''; +COMMIT; +INSERT INTO public."two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES +(1257987600000000000, 'dev1', 1.5, 1), +(1257987600000000000, 'dev1', 1.5, 2), +(1257894000000000000, 'dev2', 1.5, 1), +(1257894002000000000, 'dev1', 2.5, 3); +INSERT INTO "two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES +(1257894000000000000, 'dev2', 1.5, 2); +\set QUIET on +\o +SELECT * FROM PUBLIC."two_Partitions"; + timeCustom | device_id | series_0 | series_1 | series_2 | series_bool +---------------------+-----------+----------+----------+----------+------------- + 1257894000000000000 | dev1 | 1.5 | 1 | 2 | t + 1257894000000000000 | dev1 | 1.5 | 2 | | + 1257894000000001000 | dev1 | 2.5 | 3 | | + 1257894001000000000 | dev1 | 3.5 | 4 | | + 1257894002000000000 | dev1 | 5.5 | 6 | | t + 1257894002000000000 | dev1 | 5.5 | 7 | | f + 1257894002000000000 | dev1 | 2.5 | 3 | | + 1257897600000000000 | dev1 | 4.5 | 5 | | f + 1257987600000000000 | dev1 | 1.5 | 1 | | + 1257987600000000000 | dev1 | 1.5 | 2 | | + 1257894000000000000 | dev2 | 1.5 | 1 | | + 1257894000000000000 | dev2 | 1.5 | 2 | | +(12 rows) + +EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions"; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Append + -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.device_id, _hyper_1_1_chunk.series_0, _hyper_1_1_chunk.series_1, _hyper_1_1_chunk.series_2, _hyper_1_1_chunk.series_bool + -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.device_id, _hyper_1_2_chunk.series_0, _hyper_1_2_chunk.series_1, _hyper_1_2_chunk.series_2, _hyper_1_2_chunk.series_bool + -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.device_id, _hyper_1_3_chunk.series_0, _hyper_1_3_chunk.series_1, _hyper_1_3_chunk.series_2, _hyper_1_3_chunk.series_bool + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool +(9 rows) + +\echo "The following queries should NOT scan two_Partitions._hyper_1_1_chunk" +"The following queries should NOT scan two_Partitions._hyper_1_1_chunk" +EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE device_id = 'dev2'; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Index Scan using "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + Index Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text) +(3 rows) + +EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE device_id = 'dev'||'2'; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Index Scan using "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + Index Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text) +(3 rows) + +EXPLAIN (verbose ON, costs off) SELECT * FROM PUBLIC."two_Partitions" WHERE 'dev'||'2' = device_id; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Index Scan using "_hyper_1_4_chunk_two_Partitions_device_id_timeCustom_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + Index Cond: (_hyper_1_4_chunk.device_id = 'dev2'::text) +(3 rows) + +--test integer partition key +CREATE TABLE "int_part"(time timestamp, object_id int, temp float); +SELECT create_hypertable('"int_part"', 'time', 'object_id', 2); +NOTICE: adding not-null constraint to column "time" + create_hypertable +----------------------- + (2,public,int_part,t) +(1 row) + +INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 1, 22.5); +INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5); +--check that there are two chunks +SELECT * FROM test.show_subtables('int_part'); + Child | Tablespace +----------------------------------------+------------ + _timescaledb_internal._hyper_2_5_chunk | + _timescaledb_internal._hyper_2_6_chunk | +(2 rows) + +SELECT * FROM "int_part" WHERE object_id = 1; + time | object_id | temp +--------------------------+-----------+------ + Fri Jan 20 09:00:01 2017 | 1 | 22.5 +(1 row) + +--make sure this touches only one partititon +EXPLAIN (verbose ON, costs off) SELECT * FROM "int_part" WHERE object_id = 1; + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Index Scan using _hyper_2_5_chunk_int_part_object_id_time_idx on _timescaledb_internal._hyper_2_5_chunk + Output: _hyper_2_5_chunk."time", _hyper_2_5_chunk.object_id, _hyper_2_5_chunk.temp + Index Cond: (_hyper_2_5_chunk.object_id = 1) +(3 rows) + +--Need to verify space partitions are currently pruned in this query +--EXPLAIN (verbose ON, costs off) SELECT * FROM "two_Partitions" WHERE device_id IN ('dev2', 'dev21'); +\echo "The following shows non-aggregated queries with time desc using merge append" +"The following shows non-aggregated queries with time desc using merge append" +EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."two_Partitions" ORDER BY "timeCustom" DESC NULLS LAST limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Limit + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + -> Custom Scan (ChunkAppend) on public."two_Partitions" + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + Order: "two_Partitions"."timeCustom" DESC NULLS LAST + Startup Exclusion: false + Runtime Exclusion: false + -> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.device_id, _hyper_1_3_chunk.series_0, _hyper_1_3_chunk.series_1, _hyper_1_3_chunk.series_2, _hyper_1_3_chunk.series_bool + -> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.device_id, _hyper_1_2_chunk.series_0, _hyper_1_2_chunk.series_1, _hyper_1_2_chunk.series_2, _hyper_1_2_chunk.series_bool + -> Merge Append + Sort Key: _hyper_1_4_chunk."timeCustom" DESC NULLS LAST + -> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + -> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.device_id, _hyper_1_1_chunk.series_0, _hyper_1_1_chunk.series_1, _hyper_1_1_chunk.series_2, _hyper_1_1_chunk.series_bool +(17 rows) + +--shows that more specific indexes are used if the WHERE clauses "match", uses the series_1 index here. +EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."two_Partitions" WHERE series_1 IS NOT NULL ORDER BY "timeCustom" DESC NULLS LAST limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Limit + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + -> Custom Scan (ChunkAppend) on public."two_Partitions" + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + Order: "two_Partitions"."timeCustom" DESC NULLS LAST + Startup Exclusion: false + Runtime Exclusion: false + -> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.device_id, _hyper_1_3_chunk.series_0, _hyper_1_3_chunk.series_1, _hyper_1_3_chunk.series_2, _hyper_1_3_chunk.series_bool + -> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.device_id, _hyper_1_2_chunk.series_0, _hyper_1_2_chunk.series_1, _hyper_1_2_chunk.series_2, _hyper_1_2_chunk.series_bool + -> Merge Append + Sort Key: _hyper_1_4_chunk."timeCustom" DESC NULLS LAST + -> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + -> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.device_id, _hyper_1_1_chunk.series_0, _hyper_1_1_chunk.series_1, _hyper_1_1_chunk.series_2, _hyper_1_1_chunk.series_bool +(17 rows) + +--here the "match" is implication series_1 > 1 => series_1 IS NOT NULL +EXPLAIN (verbose ON, costs off)SELECT * FROM PUBLIC."two_Partitions" WHERE series_1 > 1 ORDER BY "timeCustom" DESC NULLS LAST limit 2; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Limit + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + -> Custom Scan (ChunkAppend) on public."two_Partitions" + Output: "two_Partitions"."timeCustom", "two_Partitions".device_id, "two_Partitions".series_0, "two_Partitions".series_1, "two_Partitions".series_2, "two_Partitions".series_bool + Order: "two_Partitions"."timeCustom" DESC NULLS LAST + Startup Exclusion: false + Runtime Exclusion: false + -> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.device_id, _hyper_1_3_chunk.series_0, _hyper_1_3_chunk.series_1, _hyper_1_3_chunk.series_2, _hyper_1_3_chunk.series_bool + Index Cond: (_hyper_1_3_chunk.series_1 > '1'::double precision) + -> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.device_id, _hyper_1_2_chunk.series_0, _hyper_1_2_chunk.series_1, _hyper_1_2_chunk.series_2, _hyper_1_2_chunk.series_bool + Index Cond: (_hyper_1_2_chunk.series_1 > '1'::double precision) + -> Merge Append + Sort Key: _hyper_1_4_chunk."timeCustom" DESC NULLS LAST + -> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.device_id, _hyper_1_4_chunk.series_0, _hyper_1_4_chunk.series_1, _hyper_1_4_chunk.series_2, _hyper_1_4_chunk.series_bool + Index Cond: (_hyper_1_4_chunk.series_1 > '1'::double precision) + -> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_series_1_idx" on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.device_id, _hyper_1_1_chunk.series_0, _hyper_1_1_chunk.series_1, _hyper_1_1_chunk.series_2, _hyper_1_1_chunk.series_bool + Index Cond: (_hyper_1_1_chunk.series_1 > '1'::double precision) +(21 rows) + +--note that without time transform things work too +EXPLAIN (verbose ON, costs off)SELECT "timeCustom" t, min(series_0) FROM PUBLIC."two_Partitions" GROUP BY t ORDER BY t DESC NULLS LAST limit 2; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: "two_Partitions"."timeCustom", (min("two_Partitions".series_0)) + -> GroupAggregate + Output: "two_Partitions"."timeCustom", min("two_Partitions".series_0) + Group Key: "two_Partitions"."timeCustom" + -> Custom Scan (ChunkAppend) on public."two_Partitions" + Output: "two_Partitions"."timeCustom", "two_Partitions".series_0 + Order: "two_Partitions"."timeCustom" DESC NULLS LAST + Startup Exclusion: false + Runtime Exclusion: false + -> Index Scan using "_hyper_1_3_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.series_0 + -> Index Scan using "_hyper_1_2_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.series_0 + -> Merge Append + Sort Key: _hyper_1_4_chunk."timeCustom" DESC NULLS LAST + -> Index Scan using "_hyper_1_4_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.series_0 + -> Index Scan using "_hyper_1_1_chunk_two_Partitions_timeCustom_device_id_idx" on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.series_0 +(20 rows) + +--The query should still use the index on timeCustom, even though the GROUP BY/ORDER BY is on the transformed time 't'. +--However, current query plans show that it does not. +EXPLAIN (verbose ON, costs off)SELECT "timeCustom"/10 t, min(series_0) FROM PUBLIC."two_Partitions" GROUP BY t ORDER BY t DESC NULLS LAST limit 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------- + Limit + Output: ((_hyper_1_1_chunk."timeCustom" / 10)), (min(_hyper_1_1_chunk.series_0)) + -> Sort + Output: ((_hyper_1_1_chunk."timeCustom" / 10)), (min(_hyper_1_1_chunk.series_0)) + Sort Key: ((_hyper_1_1_chunk."timeCustom" / 10)) DESC NULLS LAST + -> HashAggregate + Output: ((_hyper_1_1_chunk."timeCustom" / 10)), min(_hyper_1_1_chunk.series_0) + Group Key: (_hyper_1_1_chunk."timeCustom" / 10) + -> Result + Output: (_hyper_1_1_chunk."timeCustom" / 10), _hyper_1_1_chunk.series_0 + -> Append + -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.series_0 +(19 rows) + +EXPLAIN (verbose ON, costs off)SELECT "timeCustom"%10 t, min(series_0) FROM PUBLIC."two_Partitions" GROUP BY t ORDER BY t DESC NULLS LAST limit 2; + QUERY PLAN +-------------------------------------------------------------------------------------------------------- + Limit + Output: ((_hyper_1_1_chunk."timeCustom" % '10'::bigint)), (min(_hyper_1_1_chunk.series_0)) + -> Sort + Output: ((_hyper_1_1_chunk."timeCustom" % '10'::bigint)), (min(_hyper_1_1_chunk.series_0)) + Sort Key: ((_hyper_1_1_chunk."timeCustom" % '10'::bigint)) DESC NULLS LAST + -> HashAggregate + Output: ((_hyper_1_1_chunk."timeCustom" % '10'::bigint)), min(_hyper_1_1_chunk.series_0) + Group Key: (_hyper_1_1_chunk."timeCustom" % '10'::bigint) + -> Result + Output: (_hyper_1_1_chunk."timeCustom" % '10'::bigint), _hyper_1_1_chunk.series_0 + -> Append + -> Seq Scan on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk."timeCustom", _hyper_1_1_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk."timeCustom", _hyper_1_2_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk."timeCustom", _hyper_1_3_chunk.series_0 + -> Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk."timeCustom", _hyper_1_4_chunk.series_0 +(19 rows) + diff --git a/test/sql/include/join_query.sql b/test/sql/include/join_query.sql index cc2f653c6..c58ce43ce 100644 --- a/test/sql/include/join_query.sql +++ b/test/sql/include/join_query.sql @@ -2160,6 +2160,7 @@ rollback to settings; savepoint settings; set local max_parallel_workers_per_gather = 0; set local work_mem = '128kB'; +set local enable_mergejoin to false; :PREFIX select count(*) from simple r join extremely_skewed s using (id); select count(*) from simple r join extremely_skewed s using (id);