-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
\set PREFIX 'EXPLAIN (buffers off, costs off)'
-- we disable ChunkAppend and ConstraintAwareAppend here to make the exclusion easier to spot
-- otherwise those would remove the chunks from the plan during execution
SET timescaledb.enable_chunk_append TO FALSE;
SET timescaledb.enable_constraint_aware_append TO FALSE;
SET timescaledb.enable_now_constify TO FALSE;
-- plan query on complete hypertable to get a list of the chunks
:PREFIX
SELECT time
FROM metrics;
--- QUERY PLAN ---
 Append
   ->  Seq Scan on _hyper_X_X_chunk
   ->  Seq Scan on _hyper_X_X_chunk
   ->  Seq Scan on _hyper_X_X_chunk

-- all of these should have all chunk exclusion happening at plan time
:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-01-01'::timestamptz - '6h'::interval;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-01-01'::timestamptz + '6h'::interval;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone + '@ 6 hours'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '6h'::interval + '2000-01-01'::timestamptz;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone + '@ 6 hours'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-01-07'::timestamptz - '7 day 8 seconds'::interval;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone - '@ 7 days 8 secs'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-03-01'::timestamptz - '60 day'::interval;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Wed Mar 01 00:00:00 2000 PST'::timestamp with time zone - '@ 60 days'::interval))

-- test Var on right side of expression
:PREFIX
SELECT time
FROM metrics
WHERE '2000-01-01'::timestamptz - '6h'::interval > time;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE '2000-01-07'::timestamptz - '7 day'::interval > time;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone - '@ 7 days'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE '2000-03-01'::timestamptz - '60 day'::interval > time;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Wed Mar 01 00:00:00 2000 PST'::timestamp with time zone - '@ 60 days'::interval))

-- test multiple constraints
:PREFIX
SELECT time
FROM metrics
WHERE time > '2000-01-10'::timestamptz - '6h'::interval
    AND time < '2000-01-10'::timestamptz + '6h'::interval;
--- QUERY PLAN ---
 Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
   Index Cond: (("time" > ('Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval)) AND ("time" < ('Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone + '@ 6 hours'::interval)))

-- test on space-partitioned hypertable
:PREFIX
SELECT time
FROM metrics_space
WHERE time < '2000-01-01'::timestamptz - '6h'::interval
    AND device_id = 1;
--- QUERY PLAN ---
 Index Scan using _hyper_X_X_chunk_metrics_space_time_idx on _hyper_X_X_chunk
   Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))
   Filter: (device_id = 1)

-- test on compressed hypertable
:PREFIX
SELECT time
FROM metrics_compressed
WHERE time < '2000-01-01'::timestamptz - '6h'::interval;
--- QUERY PLAN ---
 Append
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
         Vectorized Filter: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))
         ->  Seq Scan on compress_hyper_X_X_chunk
               Filter: (_ts_meta_min_1 < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))

-- test on space-partitioned compressed hypertable
:PREFIX
SELECT time
FROM metrics_space_compressed
WHERE time < '2000-01-01'::timestamptz - '6h'::interval
    AND device_id = 1;
--- QUERY PLAN ---
 Custom Scan (ColumnarScan) on _hyper_X_X_chunk
   Vectorized Filter: ("time" < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval))
   ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk
         Index Cond: ((device_id = 1) AND (_ts_meta_min_1 < ('Sat Jan 01 00:00:00 2000 PST'::timestamp with time zone - '@ 6 hours'::interval)))

-- month/year intervals are not constified
:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-02-01'::timestamptz - '1 month'::interval;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-02-01'::timestamptz - '1 month - 1 day'::interval;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon -1 days'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon -1 days'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon -1 days'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-02-01'::timestamptz - '1 month + 1 day'::interval;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon 1 day'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon 1 day'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 mon 1 day'::interval))

:PREFIX
SELECT time
FROM metrics
WHERE '2000-02-01'::timestamptz - '1 year'::interval > time;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 year'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 year'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < ('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone - '@ 1 year'::interval))

-- nested expressions are not constified
:PREFIX
SELECT time
FROM metrics
WHERE time < '1 day' + '2000-02-01'::timestamptz - '1 month'::interval;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < (('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone + '@ 1 day'::interval) - '@ 1 mon'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < (('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone + '@ 1 day'::interval) - '@ 1 mon'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" < (('Tue Feb 01 00:00:00 2000 PST'::timestamp with time zone + '@ 1 day'::interval) - '@ 1 mon'::interval))

-- non-Const expressions are not constified
:PREFIX
SELECT time
FROM metrics
WHERE time > now() - '6h'::interval;
--- QUERY PLAN ---
 Append
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" > (now() - '@ 6 hours'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" > (now() - '@ 6 hours'::interval))
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_time_idx on _hyper_X_X_chunk
         Index Cond: ("time" > (now() - '@ 6 hours'::interval))

-- test NULL values
:PREFIX
SELECT time
FROM metrics
WHERE time < '2000-02-01'::timestamptz - NULL::interval;
--- QUERY PLAN ---
 Result
   One-Time Filter: false

:PREFIX
SELECT time
FROM metrics
WHERE time < NULL::timestamptz - NULL::interval;
--- QUERY PLAN ---
 Result
   One-Time Filter: false

-- test timezone changes in prepared statements
CREATE TABLE dst_test(time timestamptz NOT NULL);
SELECT table_name FROM create_hypertable('dst_test','time',chunk_time_interval:=interval '30 minutes');
 table_name 
------------
 dst_test

INSERT INTO dst_test SELECT generate_series('2022-03-27 22:00:00+01'::timestamptz,'2022-03-28 02:00:00+01'::timestamptz,'30min'::interval);
SET timezone TO UTC;
PREPARE p1 AS SELECT count(*) FROM dst_test WHERE time > '2022-03-27 00:00:00+00'::timestamptz + interval '1 day';
EXECUTE p1;
 count 
-------
     2

set timezone TO 'Europe/Berlin';
EXECUTE p1;
 count 
-------
     4

SELECT count(*) FROM dst_test WHERE time > '2022-03-27 00:00:00+00'::timestamptz + interval '1 day';
 count 
-------
     4

DEALLOCATE p1;
SET timezone TO UTC;
PREPARE p1 AS SELECT count(*) FROM dst_test WHERE time < '2022-03-27 00:00:00+00'::timestamptz + interval '1 day';
EXECUTE p1;
 count 
-------
     6

set timezone TO 'Africa/Casablanca';
EXECUTE p1;
 count 
-------
     8

SELECT count(*) FROM dst_test WHERE time < '2022-03-27 00:00:00+00'::timestamptz + interval '1 day';
 count 
-------
     8

DEALLOCATE p1;
-- do same tests with var on wrong side
SET timezone TO UTC;
PREPARE p1 AS SELECT count(*) FROM dst_test WHERE '2022-03-27 00:00:00+00'::timestamptz + interval '1 day' < time;
EXECUTE p1;
 count 
-------
     2

set timezone TO 'Europe/Berlin';
EXECUTE p1;
 count 
-------
     4

SELECT count(*) FROM dst_test WHERE '2022-03-27 00:00:00+00'::timestamptz + interval '1 day' < time;
 count 
-------
     4

DEALLOCATE p1;
SET timezone TO UTC;
PREPARE p1 AS SELECT count(*) FROM dst_test WHERE '2022-03-27 00:00:00+00'::timestamptz + interval '1 day' > time;
EXECUTE p1;
 count 
-------
     6

set timezone TO 'Africa/Casablanca';
EXECUTE p1;
 count 
-------
     8

SELECT count(*) FROM dst_test WHERE '2022-03-27 00:00:00+00'::timestamptz + interval '1 day' > time;
 count 
-------
     8

DEALLOCATE p1;
DROP TABLE dst_test;
