-- This file and its 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 (analyze, buffers off, costs off, timing off, summary off)'
\set PREFIX_VERBOSE 'EXPLAIN (analyze, buffers off, costs off, timing off, summary off, verbose)'
\set PREFIX_NO_ANALYZE 'EXPLAIN (verbose, buffers off, costs off)'
\set PREFIX_NO_VERBOSE 'EXPLAIN (buffers off, costs off)'
-- Some tweaks to get less flaky test
SET parallel_leader_participation TO off;
SET min_parallel_table_scan_size TO '0';
SET enable_incremental_sort TO off;
SELECT show_chunks('metrics_compressed') AS "TEST_TABLE" ORDER BY 1::text LIMIT 1 \gset
-- this should use ColumnarScan node
:PREFIX_VERBOSE
SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time LIMIT 5;
--- QUERY PLAN ---
 Limit (actual rows=5.00 loops=1)
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
   ->  Merge Append (actual rows=5.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=1.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.device_id = 1)
               Chunk Status: PARTIAL
               Reverse: true
               Bulk Decompression: true
               ->  Sort (actual rows=1.00 loops=1)
                     Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                           Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
                           Filter: (compress_hyper_X_X_chunk.device_id = 1)
                           Rows Removed by Filter: 16
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=5.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.device_id = 1)

-- must not use ColumnarScan node
:PREFIX_VERBOSE
SELECT * FROM ONLY :TEST_TABLE WHERE device_id = 1 ORDER BY time LIMIT 5;
--- QUERY PLAN ---
 Limit (actual rows=5.00 loops=1)
   Output: "time", device_id, v0, v1, v2, v3
   ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=5.00 loops=1)
         Output: "time", device_id, v0, v1, v2, v3
         Filter: (_hyper_X_X_chunk.device_id = 1)

-- this should use ColumnarScan node
:PREFIX_NO_VERBOSE
SELECT * FROM :TEST_TABLE UNION ALL SELECT * FROM :TEST_TABLE;
--- QUERY PLAN ---
 Append
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
         ->  Seq Scan on compress_hyper_X_X_chunk
   ->  Seq Scan on _hyper_X_X_chunk
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk _hyper_X_X_chunk_1
         ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
   ->  Seq Scan on _hyper_X_X_chunk _hyper_X_X_chunk_1

:PREFIX_NO_VERBOSE
SELECT * FROM :TEST_TABLE UNION ALL SELECT * FROM :TEST_TABLE ORDER BY time;
--- QUERY PLAN ---
 Merge Append
   Sort Key: _hyper_X_X_chunk."time"
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
         ->  Sort
               Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1
               ->  Seq Scan on compress_hyper_X_X_chunk
   ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk _hyper_X_X_chunk_1
         ->  Sort
               Sort Key: compress_hyper_X_X_chunk_1._ts_meta_min_1
               ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
   ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk _hyper_X_X_chunk_1

-- test expressions
:PREFIX
SELECT time_bucket ('1d', time),
    v1 + v2 AS "sum",
    COALESCE(NULL, v1, v2) AS "coalesce",
    NULL AS "NULL",
    'text' AS "text",
    t AS "RECORD"
FROM :TEST_TABLE t
WHERE device_id IN (1, 2)
ORDER BY time, device_id;
--- QUERY PLAN ---
 Sort (actual rows=7196.00 loops=1)
   Sort Key: t."time", t.device_id
   Sort Method: quicksort 
   ->  Result (actual rows=7196.00 loops=1)
         ->  Append (actual rows=7196.00 loops=1)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk t (actual rows=5598.00 loops=1)
                     Filter: (device_id = ANY ('{1,2}'::integer[]))
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=6.00 loops=1)
                           Filter: (device_id = ANY ('{1,2}'::integer[]))
                           Rows Removed by Filter: 12
               ->  Seq Scan on _hyper_X_X_chunk t (actual rows=1598.00 loops=1)
                     Filter: (device_id = ANY ('{1,2}'::integer[]))

-- test empty targetlist
:PREFIX SELECT FROM :TEST_TABLE;
--- QUERY PLAN ---
 Append (actual rows=17990.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=16392.00 loops=1)
         ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=18.00 loops=1)
   ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)

-- test empty resultset
:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id < 0;
--- QUERY PLAN ---
 Append (actual rows=0.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=0.00 loops=1)
         Filter: (device_id < 0)
         ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk (actual rows=0.00 loops=1)
               Index Cond: (device_id < 0)
   ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk (actual rows=0.00 loops=1)
         Index Cond: (device_id < 0)

-- test targetlist not referencing columns
:PREFIX SELECT 1 FROM :TEST_TABLE;
--- QUERY PLAN ---
 Result (actual rows=17990.00 loops=1)
   ->  Append (actual rows=17990.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=16392.00 loops=1)
               ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=18.00 loops=1)
         ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)

-- test constraints not present in targetlist
:PREFIX SELECT v1 FROM :TEST_TABLE WHERE device_id = 1 ORDER BY v1;
--- QUERY PLAN ---
 Sort (actual rows=3598.00 loops=1)
   Sort Key: _hyper_X_X_chunk.v1
   Sort Method: quicksort 
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Filter: (device_id = 1)
               ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Filter: (device_id = 1)
                     Rows Removed by Filter: 16
         ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Filter: (device_id = 1)

-- test order not present in targetlist
:PREFIX SELECT v2 FROM :TEST_TABLE WHERE device_id = 1 ORDER BY v1;
--- QUERY PLAN ---
 Sort (actual rows=3598.00 loops=1)
   Sort Key: _hyper_X_X_chunk.v1
   Sort Method: quicksort 
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Filter: (device_id = 1)
               ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Filter: (device_id = 1)
                     Rows Removed by Filter: 16
         ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Filter: (device_id = 1)

-- test column with all NULL
:PREFIX SELECT v3 FROM :TEST_TABLE WHERE device_id = 1;
--- QUERY PLAN ---
 Append (actual rows=3598.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=2000.00 loops=1)
         Filter: (device_id = 1)
         ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
               Filter: (device_id = 1)
               Rows Removed by Filter: 16
   ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)
         Filter: (device_id = 1)

--
-- test qual pushdown
--
-- v3 is not segment by or order by column so should not be pushed down
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE v3 > 10.0 ORDER BY time, device_id;
--- QUERY PLAN ---
 Sort (actual rows=719.00 loops=1)
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
   Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
   Sort Method: quicksort 
   ->  Append (actual rows=719.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=0.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Vectorized Filter: (_hyper_X_X_chunk.v3 > '10'::double precision)
               Rows Removed by Filter: 16392
               Batches Removed by Filter: 18
               Chunk Status: PARTIAL
               Bulk Decompression: true
               ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=18.00 loops=1)
                     Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
         ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk (actual rows=719.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.v3 > '10'::double precision)
               Rows Removed by Filter: 879

-- device_id constraint should be pushed down
:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Merge Append (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=1.00 loops=1)
               Filter: (device_id = 1)
               ->  Sort (actual rows=1.00 loops=1)
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                           Filter: (device_id = 1)
                           Rows Removed by Filter: 16
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk (actual rows=10.00 loops=1)
               Filter: (device_id = 1)

-- test IS NULL / IS NOT NULL
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id IS NOT NULL ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (device_id IS NOT NULL)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (device_id IS NOT NULL)
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (device_id IS NOT NULL)

:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id IS NULL ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=0.00 loops=1)
   ->  Sort (actual rows=0.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         Sort Method: quicksort 
         ->  Append (actual rows=0.00 loops=1)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=0.00 loops=1)
                     Filter: (device_id IS NULL)
                     ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk (actual rows=0.00 loops=1)
                           Index Cond: (device_id IS NULL)
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk (actual rows=0.00 loops=1)
                     Index Cond: (device_id IS NULL)

-- test IN (Const,Const)
:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id IN (1, 2) ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Sort (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         Sort Method: top-N heapsort 
         ->  Append (actual rows=7196.00 loops=1)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=5598.00 loops=1)
                     Filter: (device_id = ANY ('{1,2}'::integer[]))
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=6.00 loops=1)
                           Filter: (device_id = ANY ('{1,2}'::integer[]))
                           Rows Removed by Filter: 12
               ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)
                     Filter: (device_id = ANY ('{1,2}'::integer[]))

-- test cast pushdown
:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id = '1'::text::int ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Merge Append (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=1.00 loops=1)
               Filter: (device_id = 1)
               ->  Sort (actual rows=1.00 loops=1)
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                           Filter: (device_id = 1)
                           Rows Removed by Filter: 16
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk (actual rows=10.00 loops=1)
               Filter: (device_id = 1)

--test var op var
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = v0 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (device_id = v0)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (device_id = v0)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id < v1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (device_id < v1)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (device_id < v1)

-- test expressions
:PREFIX SELECT * FROM :TEST_TABLE WHERE device_id = 1 + 4 / 2 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Merge Append (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=10.00 loops=1)
               Filter: (device_id = 3)
               ->  Sort (actual rows=1.00 loops=1)
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=4.00 loops=1)
                           Filter: (device_id = 3)
                           Rows Removed by Filter: 14
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk (actual rows=0.00 loops=1)
               Index Cond: (device_id = 3)

-- test function calls
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = length(substring(version(), 1, 3)) ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Merge Append
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
               Filter: (device_id = length("substring"(version(), 1, 3)))
               ->  Sort
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (device_id = length("substring"(version(), 1, 3)))
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk
               Index Cond: (device_id = length("substring"(version(), 1, 3)))

--
-- test segment meta pushdown
--
-- order by column and const
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time = '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Merge Append
         Sort Key: _hyper_X_X_chunk.device_id
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
               Vectorized Filter: ("time" = 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Sort
                     Sort Key: compress_hyper_X_X_chunk.device_id
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: ((_ts_meta_min_1 <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) AND (_ts_meta_max_1 >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone))
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk
               Index Cond: ("time" = 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time < '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_min_1 < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk
                     Index Cond: ("time" < 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time <= '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_min_1 <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk
                     Index Cond: ("time" <= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time >= '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_max_1 >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: ("time" >= 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE '2000-01-01 1:00:00+0' < time ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: ('Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone < "time")

--pushdowns between order by and segment by columns
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v0 < 1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: (v0 < 1)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (v0 < 1)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v0 < device_id ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (v0 < device_id)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (v0 < device_id)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id < v0 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (device_id < v0)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (device_id < v0)

:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE v1 = device_id ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (v1 = device_id)
                     ->  Seq Scan on compress_hyper_X_X_chunk
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (v1 = device_id)

--pushdown between two order by column (not pushed down)
:PREFIX_NO_ANALYZE SELECT * FROM :TEST_TABLE WHERE v0 = v1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
   ->  Sort
         Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
                     Filter: (_hyper_X_X_chunk.v0 = _hyper_X_X_chunk.v1)
                     Chunk Status: PARTIAL
                     ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk
                           Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
               ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
                     Filter: (_hyper_X_X_chunk.v0 = _hyper_X_X_chunk.v1)

--pushdown of quals on order by and segment by cols anded together
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' AND device_id = 1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
   ->  Merge Append (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=1.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.device_id = 1)
               Vectorized Filter: (_hyper_X_X_chunk."time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               Chunk Status: PARTIAL
               Reverse: true
               Bulk Decompression: true
               ->  Sort (actual rows=1.00 loops=1)
                     Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                           Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
                           Filter: ((compress_hyper_X_X_chunk._ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) AND (compress_hyper_X_X_chunk.device_id = 1))
                           Rows Removed by Filter: 16
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=10.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Index Cond: (_hyper_X_X_chunk."time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone)
               Filter: (_hyper_X_X_chunk.device_id = 1)

--pushdown of quals on order by and segment by cols or together (not pushed down)
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time > '2000-01-01 1:00:00+0' OR device_id = 1 ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Filter: (("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1))
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: ((_ts_meta_max_1 > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1))
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: (("time" > 'Fri Dec 31 17:00:00 1999 PST'::timestamp with time zone) OR (device_id = 1))

--functions optimized as well
:PREFIX_NO_VERBOSE SELECT * FROM :TEST_TABLE WHERE time < now() ORDER BY time, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
                     Vectorized Filter: ("time" < now())
                     ->  Seq Scan on compress_hyper_X_X_chunk
                           Filter: (_ts_meta_min_1 < now())
               ->  Seq Scan on _hyper_X_X_chunk
                     Filter: ("time" < now())

-- test sort optimization interaction
:PREFIX_NO_VERBOSE SELECT time FROM :TEST_TABLE ORDER BY time DESC LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Merge Append
         Sort Key: _hyper_X_X_chunk."time" DESC
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
               ->  Sort
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_max_1 DESC
                     ->  Seq Scan on compress_hyper_X_X_chunk
         ->  Index Only Scan Backward using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk

:PREFIX_NO_ANALYZE SELECT time, device_id FROM :TEST_TABLE ORDER BY time DESC, device_id LIMIT 10;
--- QUERY PLAN ---
 Limit
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
   ->  Sort
         Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
         Sort Key: _hyper_X_X_chunk."time" DESC, _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
                     Chunk Status: PARTIAL
                     ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk
                           Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
               ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id

:PREFIX_NO_VERBOSE SELECT time, device_id FROM :TEST_TABLE ORDER BY device_id, time DESC LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Merge Append
         Sort Key: _hyper_X_X_chunk.device_id, _hyper_X_X_chunk."time" DESC
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk
               ->  Sort
                     Sort Key: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_min_1 DESC, compress_hyper_X_X_chunk._ts_meta_max_1 DESC
                     ->  Seq Scan on compress_hyper_X_X_chunk
         ->  Sort
               Sort Key: _hyper_X_X_chunk.device_id, _hyper_X_X_chunk."time" DESC
               ->  Seq Scan on _hyper_X_X_chunk

-- test aggregate
:PREFIX_NO_ANALYZE SELECT count(*) FROM :TEST_TABLE;
--- QUERY PLAN ---
 Aggregate
   Output: count(*)
   ->  Append
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
               Chunk Status: PARTIAL
               ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk
                     Output: compress_hyper_X_X_chunk._ts_meta_count
         ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk

-- test aggregate with GROUP BY
:PREFIX_NO_ANALYZE SELECT count(*) FROM :TEST_TABLE GROUP BY device_id ORDER BY device_id;
--- QUERY PLAN ---
 Sort
   Output: (count(*)), _hyper_X_X_chunk.device_id
   Sort Key: _hyper_X_X_chunk.device_id
   ->  HashAggregate
         Output: count(*), _hyper_X_X_chunk.device_id
         Group Key: _hyper_X_X_chunk.device_id
         ->  Append
               ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk.device_id
                     Chunk Status: PARTIAL
                     ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk
                           Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
               ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk
                     Output: _hyper_X_X_chunk.device_id

-- test window functions with GROUP BY
:PREFIX_NO_ANALYZE SELECT sum(count(*)) OVER () FROM :TEST_TABLE GROUP BY device_id ORDER BY device_id;
--- QUERY PLAN ---
 Sort
   Output: (sum((count(*))) OVER (?)), _hyper_X_X_chunk.device_id
   Sort Key: _hyper_X_X_chunk.device_id
   ->  WindowAgg
         Output: sum((count(*))) OVER (?), _hyper_X_X_chunk.device_id
         ->  HashAggregate
               Output: _hyper_X_X_chunk.device_id, count(*)
               Group Key: _hyper_X_X_chunk.device_id
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
                           Output: _hyper_X_X_chunk.device_id
                           Chunk Status: PARTIAL
                           ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk
                                 Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
                     ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk
                           Output: _hyper_X_X_chunk.device_id

-- test CTE
:PREFIX WITH q AS (
  SELECT v1 FROM :TEST_TABLE ORDER BY time
)
SELECT * FROM q ORDER BY v1;
--- QUERY PLAN ---
 Sort (actual rows=17990.00 loops=1)
   Sort Key: q.v1
   Sort Method: quicksort 
   ->  Subquery Scan on q (actual rows=17990.00 loops=1)
         ->  Merge Append (actual rows=17990.00 loops=1)
               Sort Key: _hyper_X_X_chunk."time"
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=16392.00 loops=1)
                     ->  Sort (actual rows=18.00 loops=1)
                           Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1
                           Sort Method: quicksort 
                           ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=18.00 loops=1)
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk (actual rows=1598.00 loops=1)

-- test CTE join
:PREFIX WITH q1 AS (
  SELECT time, v1 FROM :TEST_TABLE WHERE device_id = 1 ORDER BY time
),
q2 AS (
  SELECT time, v2 FROM :TEST_TABLE WHERE device_id = 2 ORDER BY time
)
SELECT * FROM q1 INNER JOIN q2 ON q1.time = q2.time ORDER BY q1.time;
--- QUERY PLAN ---
 Merge Join (actual rows=3598.00 loops=1)
   Merge Cond: (_hyper_X_X_chunk."time" = _hyper_X_X_chunk_1."time")
   ->  Merge Append (actual rows=3598.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time"
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=3598.00 loops=1)
               Filter: (device_id = 2)
               ->  Sort (actual rows=4.00 loops=1)
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                     Sort Method: quicksort 
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=4.00 loops=1)
                           Filter: (device_id = 2)
                           Rows Removed by Filter: 14
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk (actual rows=0.00 loops=1)
               Index Cond: (device_id = 2)
   ->  Materialize (actual rows=3598.00 loops=1)
         ->  Merge Append (actual rows=3598.00 loops=1)
               Sort Key: _hyper_X_X_chunk_1."time"
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk _hyper_X_X_chunk_1 (actual rows=2000.00 loops=1)
                     Filter: (device_id = 1)
                     ->  Sort (actual rows=2.00 loops=1)
                           Sort Key: compress_hyper_X_X_chunk_1._ts_meta_min_1, compress_hyper_X_X_chunk_1._ts_meta_max_1
                           Sort Method: quicksort 
                           ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1 (actual rows=2.00 loops=1)
                                 Filter: (device_id = 1)
                                 Rows Removed by Filter: 16
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk _hyper_X_X_chunk_1 (actual rows=1598.00 loops=1)
                     Filter: (device_id = 1)

--
-- test indexes
--
SET enable_seqscan TO FALSE;
-- IndexScans should work
:PREFIX_VERBOSE SELECT time, device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
--- QUERY PLAN ---
 Sort (actual rows=3598.00 loops=1)
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
   Sort Key: _hyper_X_X_chunk."time"
   Sort Method: quicksort 
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
               Filter: (_hyper_X_X_chunk.device_id = 1)
               Chunk Status: PARTIAL
               Reverse: true
               Bulk Decompression: true
               ->  Index Scan Backward using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
                     Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
         ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id
               Index Cond: (_hyper_X_X_chunk.device_id = 1)

-- globs should not plan IndexOnlyScans
:PREFIX_VERBOSE SELECT * FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id, time;
--- QUERY PLAN ---
 Sort (actual rows=3598.00 loops=1)
   Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
   Sort Key: _hyper_X_X_chunk."time"
   Sort Method: quicksort 
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.device_id = 1)
               Chunk Status: PARTIAL
               Reverse: true
               Bulk Decompression: true
               ->  Index Scan Backward using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Output: compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3, compress_hyper_X_X_chunk._ts_meta_count
                     Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Output: _hyper_X_X_chunk."time", _hyper_X_X_chunk.device_id, _hyper_X_X_chunk.v0, _hyper_X_X_chunk.v1, _hyper_X_X_chunk.v2, _hyper_X_X_chunk.v3
               Filter: (_hyper_X_X_chunk.device_id = 1)

-- whole row reference should work
:PREFIX_VERBOSE SELECT test_table FROM :TEST_TABLE AS test_table WHERE device_id = 1 ORDER BY device_id, time;
--- QUERY PLAN ---
 Sort (actual rows=3598.00 loops=1)
   Output: test_table.*, test_table.device_id, test_table."time"
   Sort Key: test_table."time"
   Sort Method: quicksort 
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk test_table (actual rows=2000.00 loops=1)
               Output: test_table.*, test_table.device_id, test_table."time"
               Filter: (test_table.device_id = 1)
               Chunk Status: PARTIAL
               Reverse: true
               Bulk Decompression: true
               ->  Index Scan Backward using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk."time", compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1, compress_hyper_X_X_chunk._ts_meta_count, compress_hyper_X_X_chunk.v0, compress_hyper_X_X_chunk.v1, compress_hyper_X_X_chunk.v2, compress_hyper_X_X_chunk.v3
                     Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
         ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _timescaledb_internal._hyper_X_X_chunk test_table (actual rows=1598.00 loops=1)
               Output: test_table.*, test_table.device_id, test_table."time"
               Filter: (test_table.device_id = 1)

-- even when we select only a segmentby column, we still need count
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id = 1 ORDER BY device_id;
--- QUERY PLAN ---
 Append (actual rows=3598.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Filter: (_hyper_X_X_chunk.device_id = 1)
         Chunk Status: PARTIAL
         Bulk Decompression: false
         ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
               Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
               Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
   ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Index Cond: (_hyper_X_X_chunk.device_id = 1)

:PREFIX_VERBOSE SELECT count(*) FROM :TEST_TABLE WHERE device_id = 1;
--- QUERY PLAN ---
 Aggregate (actual rows=1.00 loops=1)
   Output: count(*)
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Filter: (_hyper_X_X_chunk.device_id = 1)
               Chunk Status: PARTIAL
               Bulk Decompression: false
               ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
                     Index Cond: (compress_hyper_X_X_chunk.device_id = 1)
         ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Index Cond: (_hyper_X_X_chunk.device_id = 1)

--ensure that we can get a nested loop
SET enable_seqscan TO TRUE;
SET enable_hashjoin TO FALSE;
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1));
--- QUERY PLAN ---
 Append (actual rows=3598.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Filter: (_hyper_X_X_chunk.device_id = 1)
         Chunk Status: PARTIAL
         Bulk Decompression: false
         ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
               Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
               Filter: (compress_hyper_X_X_chunk.device_id = 1)
               Rows Removed by Filter: 16
   ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Filter: (_hyper_X_X_chunk.device_id = 1)

--with multiple values can get a nested loop.
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN ( VALUES (1), (2));
--- QUERY PLAN ---
 Nested Loop (actual rows=7196.00 loops=1)
   Output: _hyper_X_X_chunk.device_id
   ->  Unique (actual rows=2.00 loops=1)
         Output: "*VALUES*".column1
         ->  Sort (actual rows=2.00 loops=1)
               Output: "*VALUES*".column1
               Sort Key: "*VALUES*".column1
               Sort Method: quicksort 
               ->  Values Scan on "*VALUES*" (actual rows=2.00 loops=1)
                     Output: "*VALUES*".column1
   ->  Append (actual rows=3598.00 loops=2)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2799.00 loops=2)
               Output: _hyper_X_X_chunk.device_id
               Chunk Status: PARTIAL
               Bulk Decompression: false
               ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=3.00 loops=2)
                     Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
                     Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
         ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk (actual rows=799.00 loops=2)
               Output: _hyper_X_X_chunk.device_id
               Filter: ("*VALUES*".column1 = _hyper_X_X_chunk.device_id)
               Rows Removed by Filter: 799

RESET enable_hashjoin;
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1));
--- QUERY PLAN ---
 Append (actual rows=3598.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=2000.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Filter: (_hyper_X_X_chunk.device_id = 1)
         Chunk Status: PARTIAL
         Bulk Decompression: false
         ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
               Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
               Filter: (compress_hyper_X_X_chunk.device_id = 1)
               Rows Removed by Filter: 16
   ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
         Output: _hyper_X_X_chunk.device_id
         Filter: (_hyper_X_X_chunk.device_id = 1)

--with multiple values can get a semi-join or nested loop depending on seq_page_cost.
:PREFIX_VERBOSE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
--- QUERY PLAN ---
 Hash Semi Join (actual rows=7196.00 loops=1)
   Output: _hyper_X_X_chunk.device_id
   Hash Cond: (_hyper_X_X_chunk.device_id = "*VALUES*".column1)
   ->  Append (actual rows=17990.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk (actual rows=16392.00 loops=1)
               Output: _hyper_X_X_chunk.device_id
               Chunk Status: PARTIAL
               Bulk Decompression: false
               ->  Seq Scan on _timescaledb_internal.compress_hyper_X_X_chunk (actual rows=18.00 loops=1)
                     Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
         ->  Seq Scan on _timescaledb_internal._hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Output: _hyper_X_X_chunk.device_id
   ->  Hash (actual rows=2.00 loops=1)
         Output: "*VALUES*".column1
         ->  Values Scan on "*VALUES*" (actual rows=2.00 loops=1)
               Output: "*VALUES*".column1

SET seq_page_cost = 100;
-- loop/row counts of this query is different on windows so we run it without analyze
:PREFIX_NO_ANALYZE SELECT device_id FROM :TEST_TABLE WHERE device_id IN (VALUES (1), (2));
--- QUERY PLAN ---
 Nested Loop
   Output: _hyper_X_X_chunk.device_id
   ->  Unique
         Output: "*VALUES*".column1
         ->  Sort
               Output: "*VALUES*".column1
               Sort Key: "*VALUES*".column1
               ->  Values Scan on "*VALUES*"
                     Output: "*VALUES*".column1
   ->  Append
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_X_X_chunk
               Output: _hyper_X_X_chunk.device_id
               Chunk Status: PARTIAL
               ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on _timescaledb_internal.compress_hyper_X_X_chunk
                     Output: compress_hyper_X_X_chunk.device_id, compress_hyper_X_X_chunk._ts_meta_count
                     Index Cond: (compress_hyper_X_X_chunk.device_id = "*VALUES*".column1)
         ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _timescaledb_internal._hyper_X_X_chunk
               Output: _hyper_X_X_chunk.device_id
               Index Cond: (_hyper_X_X_chunk.device_id = "*VALUES*".column1)

RESET seq_page_cost;
-- test view
CREATE OR REPLACE VIEW compressed_view AS SELECT time, device_id, v1, v2 FROM :TEST_TABLE;
:PREFIX SELECT * FROM compressed_view WHERE device_id = 1 ORDER BY time DESC LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Merge Append (actual rows=10.00 loops=1)
         Sort Key: _hyper_X_X_chunk."time" DESC
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=10.00 loops=1)
               Filter: (device_id = 1)
               ->  Sort (actual rows=1.00 loops=1)
                     Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1 DESC, compress_hyper_X_X_chunk._ts_meta_max_1 DESC
                     Sort Method: quicksort 
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                           Filter: (device_id = 1)
                           Rows Removed by Filter: 16
         ->  Index Scan Backward using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk (actual rows=1.00 loops=1)
               Filter: (device_id = 1)

DROP VIEW compressed_view;
-- test INNER JOIN
:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1
    INNER JOIN :TEST_TABLE m2 ON m1.time = m2.time
        AND m1.device_id = m2.device_id
    ORDER BY m1.time,
        m1.device_id
    LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id
         ->  Hash Join
               Hash Cond: ((m1."time" = m2."time") AND (m1.device_id = m2.device_id))
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           ->  Seq Scan on compress_hyper_X_X_chunk
                     ->  Seq Scan on _hyper_X_X_chunk m1
               ->  Hash
                     ->  Append
                           ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                                 ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                           ->  Seq Scan on _hyper_X_X_chunk m2

:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1
    INNER JOIN :TEST_TABLE m2 ON m1.time = m2.time
    INNER JOIN :TEST_TABLE m3 ON m2.time = m3.time
        AND m1.device_id = m2.device_id
        AND m3.device_id = 3
    ORDER BY m1.time,
        m1.device_id
    LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id
         ->  Hash Join
               Hash Cond: ((m2."time" = m1."time") AND (m2.device_id = m1.device_id))
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                           ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                     ->  Seq Scan on _hyper_X_X_chunk m2
               ->  Hash
                     ->  Hash Join
                           Hash Cond: (m1."time" = m3."time")
                           ->  Append
                                 ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                                       ->  Seq Scan on compress_hyper_X_X_chunk
                                 ->  Seq Scan on _hyper_X_X_chunk m1
                           ->  Hash
                                 ->  Append
                                       ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m3
                                             Filter: (device_id = 3)
                                             ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_2
                                                   Filter: (device_id = 3)
                                       ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk m3
                                             Index Cond: (device_id = 3)

RESET min_parallel_table_scan_size;
:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1
    INNER JOIN :TEST_TABLE m2 ON m1.time = m2.time
        AND m1.device_id = 1
        AND m2.device_id = 2
    ORDER BY m1.time,
        m1.device_id,
        m2.time,
        m2.device_id
    LIMIT 100;
--- QUERY PLAN ---
 Limit
   ->  Merge Join
         Merge Cond: (m2."time" = m1."time")
         ->  Merge Append
               Sort Key: m2."time"
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                     Filter: (device_id = 2)
                     ->  Sort
                           Sort Key: compress_hyper_X_X_chunk_1._ts_meta_min_1, compress_hyper_X_X_chunk_1._ts_meta_max_1
                           ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                                 Filter: (device_id = 2)
               ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk m2
                     Index Cond: (device_id = 2)
         ->  Materialize
               ->  Merge Append
                     Sort Key: m1."time"
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           Filter: (device_id = 1)
                           ->  Sort
                                 Sort Key: compress_hyper_X_X_chunk._ts_meta_min_1, compress_hyper_X_X_chunk._ts_meta_max_1
                                 ->  Seq Scan on compress_hyper_X_X_chunk
                                       Filter: (device_id = 1)
                     ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk m1
                           Filter: (device_id = 1)

:PREFIX_NO_VERBOSE
SELECT *
FROM metrics m1
    INNER JOIN metrics_space m2 ON m1.time = m2.time
        AND m1.device_id = 1
        AND m2.device_id = 2
	WHERE m1.v1 = 3 -- additional filter to force m1 as inner relation in join
    ORDER BY m1.time,
        m1.device_id,
        m2.time,
        m2.device_id
    LIMIT 100;
--- QUERY PLAN ---
 Limit
   ->  Merge Join
         Merge Cond: (m1."time" = m2."time")
         ->  Custom Scan (ChunkAppend) on metrics m1
               Order: m1."time"
               ->  Index Scan Backward using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk m1_1
                     Index Cond: (device_id = 1)
                     Filter: (v1 = 3)
               ->  Index Scan Backward using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk m1_2
                     Index Cond: (device_id = 1)
                     Filter: (v1 = 3)
               ->  Index Scan Backward using _hyper_X_X_chunk_metrics_device_id_time_idx on _hyper_X_X_chunk m1_3
                     Index Cond: (device_id = 1)
                     Filter: (v1 = 3)
         ->  Materialize
               ->  Custom Scan (ChunkAppend) on metrics_space m2
                     Order: m2."time"
                     ->  Index Scan using _hyper_X_X_chunk_metrics_space_device_id_time_idx on _hyper_X_X_chunk m2_1
                           Index Cond: (device_id = 2)
                     ->  Index Scan using _hyper_X_X_chunk_metrics_space_device_id_time_idx on _hyper_X_X_chunk m2_2
                           Index Cond: (device_id = 2)
                     ->  Index Scan using _hyper_X_X_chunk_metrics_space_device_id_time_idx on _hyper_X_X_chunk m2_3
                           Index Cond: (device_id = 2)

-- test OUTER JOIN
SET min_parallel_table_scan_size TO '0';
-- Disable merge join to get stable tests. These queries uses hash
-- joins.
SET enable_mergejoin TO off;
:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1
    LEFT OUTER JOIN :TEST_TABLE m2 ON m1.time = m2.time
    AND m1.device_id = m2.device_id
ORDER BY m1.time,
    m1.device_id
LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id
         ->  Hash Left Join
               Hash Cond: ((m1."time" = m2."time") AND (m1.device_id = m2.device_id))
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           ->  Seq Scan on compress_hyper_X_X_chunk
                     ->  Seq Scan on _hyper_X_X_chunk m1
               ->  Hash
                     ->  Append
                           ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                                 ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                           ->  Seq Scan on _hyper_X_X_chunk m2

RESET min_parallel_table_scan_size;
:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1
    LEFT OUTER JOIN :TEST_TABLE m2 ON m1.time = m2.time
    AND m1.device_id = 1
    AND m2.device_id = 2
ORDER BY m1.time,
    m1.device_id,
    m2.time,
    m2.device_id
LIMIT 100;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id, m2."time", m2.device_id
         ->  Hash Left Join
               Hash Cond: (m1."time" = m2."time")
               Join Filter: (m1.device_id = 1)
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           ->  Seq Scan on compress_hyper_X_X_chunk
                     ->  Seq Scan on _hyper_X_X_chunk m1
               ->  Hash
                     ->  Append
                           ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                                 Filter: (device_id = 2)
                                 ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                                       Filter: (device_id = 2)
                           ->  Index Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk m2
                                 Index Cond: (device_id = 2)

-- test implicit self-join
:PREFIX_NO_VERBOSE
SELECT *
FROM :TEST_TABLE m1,
    :TEST_TABLE m2
WHERE m1.time = m2.time
ORDER BY m1.time,
    m1.device_id,
    m2.time,
    m2.device_id
LIMIT 20;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id, m2.device_id
         ->  Hash Join
               Hash Cond: (m1."time" = m2."time")
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           ->  Seq Scan on compress_hyper_X_X_chunk
                     ->  Seq Scan on _hyper_X_X_chunk m1
               ->  Hash
                     ->  Append
                           ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                                 ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                           ->  Seq Scan on _hyper_X_X_chunk m2

-- test self-join with sub-query
:PREFIX_NO_VERBOSE
SELECT *
FROM (
    SELECT *
    FROM :TEST_TABLE m1) m1
    INNER JOIN (
        SELECT *
        FROM :TEST_TABLE m2) m2 ON m1.time = m2.time
ORDER BY m1.time,
    m1.device_id,
    m2.device_id
LIMIT 10;
--- QUERY PLAN ---
 Limit
   ->  Sort
         Sort Key: m1."time", m1.device_id, m2.device_id
         ->  Hash Join
               Hash Cond: (m1."time" = m2."time")
               ->  Append
                     ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1
                           ->  Seq Scan on compress_hyper_X_X_chunk
                     ->  Seq Scan on _hyper_X_X_chunk m1
               ->  Hash
                     ->  Append
                           ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m2
                                 ->  Seq Scan on compress_hyper_X_X_chunk compress_hyper_X_X_chunk_1
                           ->  Seq Scan on _hyper_X_X_chunk m2

RESET enable_mergejoin;
:PREFIX
SELECT *
FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g (time)
        INNER JOIN LATERAL (
            SELECT time
            FROM :TEST_TABLE m1
            WHERE m1.time = g.time
            LIMIT 1) m1 ON TRUE;
--- QUERY PLAN ---
 Nested Loop (actual rows=5.00 loops=1)
   ->  Function Scan on generate_series g (actual rows=32.00 loops=1)
   ->  Limit (actual rows=0.00 loops=32)
         ->  Append (actual rows=0.00 loops=32)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1 (actual rows=0.00 loops=32)
                     Filter: ("time" = g."time")
                     Rows Removed by Filter: 81
                     ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=0.00 loops=32)
                           Filter: ((_ts_meta_min_1 <= g."time") AND (_ts_meta_max_1 >= g."time"))
                           Rows Removed by Filter: 16
               ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_time_idx on _hyper_X_X_chunk m1 (actual rows=0.00 loops=27)
                     Index Cond: ("time" = g."time")

-- test prepared statement
SET plan_cache_mode TO force_generic_plan;
PREPARE prep AS SELECT count(time) FROM :TEST_TABLE WHERE device_id = 1;
:PREFIX EXECUTE prep;
--- QUERY PLAN ---
 Aggregate (actual rows=1.00 loops=1)
   ->  Append (actual rows=3598.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk (actual rows=2000.00 loops=1)
               Filter: (device_id = 1)
               ->  Seq Scan on compress_hyper_X_X_chunk (actual rows=2.00 loops=1)
                     Filter: (device_id = 1)
                     Rows Removed by Filter: 16
         ->  Seq Scan on _hyper_X_X_chunk (actual rows=1598.00 loops=1)
               Filter: (device_id = 1)

EXECUTE prep;
 count 
-------
  3598

EXECUTE prep;
 count 
-------
  3598

EXECUTE prep;
 count 
-------
  3598

EXECUTE prep;
 count 
-------
  3598

EXECUTE prep;
 count 
-------
  3598

EXECUTE prep;
 count 
-------
  3598

DEALLOCATE prep;
-- test prepared statement with params pushdown
PREPARE param_prep (int) AS
SELECT *
FROM generate_series('2000-01-01'::timestamptz, '2000-02-01'::timestamptz, '1d'::interval) g (time)
        INNER JOIN LATERAL (
            SELECT time
            FROM :TEST_TABLE m1
            WHERE m1.time = g.time
                AND device_id = $1
            LIMIT 1) m1 ON TRUE;
:PREFIX EXECUTE param_prep (1);
--- QUERY PLAN ---
 Nested Loop (actual rows=5.00 loops=1)
   ->  Function Scan on generate_series g (actual rows=32.00 loops=1)
   ->  Limit (actual rows=0.00 loops=32)
         ->  Append (actual rows=0.00 loops=32)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1 (actual rows=0.00 loops=32)
                     Filter: (("time" = g."time") AND (device_id = $1))
                     Rows Removed by Filter: 50
                     ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk (actual rows=0.00 loops=32)
                           Index Cond: ((device_id = $1) AND (_ts_meta_min_1 <= g."time") AND (_ts_meta_max_1 >= g."time"))
               ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk m1 (actual rows=0.00 loops=29)
                     Index Cond: ((device_id = $1) AND ("time" = g."time"))

:PREFIX EXECUTE param_prep (2);
--- QUERY PLAN ---
 Nested Loop (actual rows=5.00 loops=1)
   ->  Function Scan on generate_series g (actual rows=32.00 loops=1)
   ->  Limit (actual rows=0.00 loops=32)
         ->  Append (actual rows=0.00 loops=32)
               ->  Custom Scan (ColumnarScan) on _hyper_X_X_chunk m1 (actual rows=0.00 loops=32)
                     Filter: (("time" = g."time") AND (device_id = $1))
                     Rows Removed by Filter: 81
                     ->  Index Scan using compress_hyper_X_X_chunk_device_id__ts_meta_min_1__ts_meta_idx on compress_hyper_X_X_chunk (actual rows=0.00 loops=32)
                           Index Cond: ((device_id = $1) AND (_ts_meta_min_1 <= g."time") AND (_ts_meta_max_1 >= g."time"))
               ->  Index Only Scan using _hyper_X_X_chunk_metrics_compressed_device_id_time_idx on _hyper_X_X_chunk m1 (actual rows=0.00 loops=27)
                     Index Cond: ((device_id = $1) AND ("time" = g."time"))

EXECUTE param_prep (1);
             time             |             time             
------------------------------+------------------------------
 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
 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
 Wed Jan 05 00:00:00 2000 PST | Wed Jan 05 00:00:00 2000 PST

EXECUTE param_prep (2);
             time             |             time             
------------------------------+------------------------------
 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
 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
 Wed Jan 05 00:00:00 2000 PST | Wed Jan 05 00:00:00 2000 PST

EXECUTE param_prep (1);
             time             |             time             
------------------------------+------------------------------
 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
 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
 Wed Jan 05 00:00:00 2000 PST | Wed Jan 05 00:00:00 2000 PST

EXECUTE param_prep (2);
             time             |             time             
------------------------------+------------------------------
 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
 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
 Wed Jan 05 00:00:00 2000 PST | Wed Jan 05 00:00:00 2000 PST

EXECUTE param_prep (1);
             time             |             time             
------------------------------+------------------------------
 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
 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
 Wed Jan 05 00:00:00 2000 PST | Wed Jan 05 00:00:00 2000 PST

DEALLOCATE param_prep;
RESET plan_cache_mode;
-- test hypertable being non-toplevel equivalence member #6925
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
CREATE TABLE i6925_t2(LIKE i6925_t1);
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
 table_name 
------------
 i6925_t1

ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
 count 
-------
     1

SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
 queryid | lag 
---------+-----
       1 |    

DROP TABLE i6925_t1;
DROP TABLE i6925_t2;
