-- 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 run these with analyze to confirm that nodes that are not
-- needed to fulfill the limit are not executed
-- unfortunately this doesn't work on PostgreSQL 9.6 which lacks
-- the ability to turn off analyze timing summary so we run
-- them without ANALYZE on PostgreSQL 9.6, but since LATERAL plans
-- are different across versions we need version specific output
-- here anyway.
\set TEST_BASE_NAME plan_ordered_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 result" --label "Optimized result" %s %s', :'TEST_RESULTS_UNOPTIMIZED', :'TEST_RESULTS_OPTIMIZED') as "DIFF_CMD"
\gset
\set PREFIX 'EXPLAIN (analyze, buffers off, costs off, timing off, summary off)'
\set PREFIX_NO_ANALYZE 'EXPLAIN (buffers off, 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 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
    RETURN '2000-01-08T0:00:00+0'::timestamptz;
END;
$BODY$;
CREATE TABLE devices(device_id INT PRIMARY KEY, name TEXT);
INSERT INTO devices VALUES
(1,'Device 1'),
(2,'Device 2'),
(3,'Device 3');
-- create a second table where we create chunks in reverse order
CREATE TABLE ordered_append_reverse(time timestamptz NOT NULL, device_id INT, value float);
SELECT create_hypertable('ordered_append_reverse','time');
          create_hypertable          
-------------------------------------
 (1,public,ordered_append_reverse,t)

INSERT INTO ordered_append_reverse SELECT generate_series('2000-01-18'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 0.5;
-- table where dimension column is last column
CREATE TABLE IF NOT EXISTS dimension_last(
    id INT8 NOT NULL,
    device_id INT NOT NULL,
    name TEXT NOT NULL,
    time timestamptz NOT NULL
);
SELECT create_hypertable('dimension_last', 'time', chunk_time_interval => interval '1day', if_not_exists => True);
      create_hypertable      
-----------------------------
 (2,public,dimension_last,t)

-- table with only dimension column
CREATE TABLE IF NOT EXISTS dimension_only(
    time timestamptz NOT NULL
);
SELECT create_hypertable('dimension_only', 'time', chunk_time_interval => interval '1day', if_not_exists => True);
      create_hypertable      
-----------------------------
 (3,public,dimension_only,t)

INSERT INTO dimension_last SELECT 1,1,'Device 1',generate_series('2000-01-01 0:00:00+0'::timestamptz,'2000-01-04 23:59:00+0'::timestamptz,'1m'::interval);
INSERT INTO dimension_only VALUES
('2000-01-01'),
('2000-01-03'),
('2000-01-05'),
('2000-01-07');
ANALYZE devices;
ANALYZE ordered_append_reverse;
ANALYZE dimension_last;
ANALYZE dimension_only;
-- create hypertable with indexes not on all chunks
CREATE TABLE ht_missing_indexes(time timestamptz NOT NULL, device_id int, value float);
SELECT create_hypertable('ht_missing_indexes','time');
        create_hypertable        
---------------------------------
 (4,public,ht_missing_indexes,t)

INSERT INTO ht_missing_indexes SELECT generate_series('2000-01-01'::timestamptz,'2000-01-18'::timestamptz,'1m'::interval), 1, 0.5;
INSERT INTO ht_missing_indexes SELECT generate_series('2000-01-01'::timestamptz,'2000-01-18'::timestamptz,'1m'::interval), 2, 1.5;
INSERT INTO ht_missing_indexes SELECT generate_series('2000-01-01'::timestamptz,'2000-01-18'::timestamptz,'1m'::interval), 3, 2.5;
-- drop index from 2nd chunk of ht_missing_indexes
SELECT format('%I.%I',i.schemaname,i.indexname) AS "INDEX_NAME"
FROM _timescaledb_catalog.chunk c
INNER JOIN _timescaledb_catalog.hypertable ht ON c.hypertable_id = ht.id
INNER JOIN pg_indexes i ON i.schemaname = c.schema_name AND i.tablename=c.table_name
WHERE ht.table_name = 'ht_missing_indexes'
ORDER BY c.id LIMIT 1 OFFSET 1 \gset
DROP INDEX :INDEX_NAME;
ANALYZE ht_missing_indexes;
-- create hypertable with with dropped columns
CREATE TABLE ht_dropped_columns(c1 int, c2 int, c3 int, c4 int, c5 int, time timestamptz NOT NULL, device_id int, value float);
SELECT create_hypertable('ht_dropped_columns','time');
        create_hypertable        
---------------------------------
 (5,public,ht_dropped_columns,t)

ALTER TABLE ht_dropped_columns DROP COLUMN c1;
INSERT INTO ht_dropped_columns(time,device_id,value) SELECT generate_series('2000-01-01'::timestamptz,'2000-01-02'::timestamptz,'1m'::interval), 1, 0.5;
ALTER TABLE ht_dropped_columns DROP COLUMN c2;
INSERT INTO ht_dropped_columns(time,device_id,value) SELECT generate_series('2000-01-08'::timestamptz,'2000-01-09'::timestamptz,'1m'::interval), 1, 0.5;
ALTER TABLE ht_dropped_columns DROP COLUMN c3;
INSERT INTO ht_dropped_columns(time,device_id,value) SELECT generate_series('2000-01-15'::timestamptz,'2000-01-16'::timestamptz,'1m'::interval), 1, 0.5;
ALTER TABLE ht_dropped_columns DROP COLUMN c4;
INSERT INTO ht_dropped_columns(time,device_id,value) SELECT generate_series('2000-01-22'::timestamptz,'2000-01-23'::timestamptz,'1m'::interval), 1, 0.5;
ALTER TABLE ht_dropped_columns DROP COLUMN c5;
INSERT INTO ht_dropped_columns(time,device_id,value) SELECT generate_series('2000-01-29'::timestamptz,'2000-01-30'::timestamptz,'1m'::interval), 1, 0.5;
ANALYZE ht_dropped_columns;
CREATE TABLE space2(time timestamptz NOT NULL, device_id int NOT NULL, tag_id int NOT NULL, value float);
SELECT create_hypertable('space2','time','device_id',number_partitions:=3);
  create_hypertable  
---------------------
 (6,public,space2,t)

SELECT add_dimension('space2','tag_id',number_partitions:=3);
       add_dimension        
----------------------------
 (8,public,space2,tag_id,t)

INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 1, 1.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 1, 2.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 3, 1, 3.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 2, 1.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 2, 2.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 3, 2, 3.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 3, 1.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 3, 2.5;
INSERT INTO space2 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 3, 3, 3.5;
ANALYZE space2;
CREATE TABLE space3(time timestamptz NOT NULL, x int NOT NULL, y int NOT NULL, z int NOT NULL, value float);
SELECT create_hypertable('space3','time','x',number_partitions:=2);
  create_hypertable  
---------------------
 (7,public,space3,t)

SELECT add_dimension('space3','y',number_partitions:=2);
     add_dimension      
------------------------
 (11,public,space3,y,t)

SELECT add_dimension('space3','z',number_partitions:=2);
     add_dimension      
------------------------
 (12,public,space3,z,t)

INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 1, 1, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 1, 2, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 2, 1, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 1, 2, 2, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 1, 1, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 1, 2, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 2, 1, 1.5;
INSERT INTO space3 SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 2, 2, 2, 1.5;
ANALYZE space3;
CREATE TABLE sortopt_test(time timestamptz NOT NULL, device TEXT);
SELECT create_hypertable('sortopt_test','time',create_default_indexes:=false);
     create_hypertable     
---------------------------
 (8,public,sortopt_test,t)

-- since alpine does not support locales we cant test collations in our ci
-- CREATE COLLATION IF NOT EXISTS en_US(LOCALE='en_US.utf8');
-- CREATE INDEX time_device_utf8 ON sortopt_test(time, device COLLATE "en_US");
CREATE INDEX time_device_nullsfirst ON sortopt_test(time, device NULLS FIRST);
CREATE INDEX time_device_nullslast ON sortopt_test(time, device DESC NULLS LAST);
INSERT INTO sortopt_test SELECT generate_series('2000-01-10'::timestamptz,'2000-01-01'::timestamptz,'-1m'::interval), 'Device 1';
ANALYZE sortopt_test;
\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.
-- print chunks ordered by time to ensure ordering we want
SELECT
  ht.table_name AS hypertable,
  c.table_name AS chunk,
  ds.range_start
FROM
  _timescaledb_catalog.chunk c
  INNER JOIN LATERAL(SELECT * FROM _timescaledb_catalog.chunk_constraint cc WHERE c.id = cc.chunk_id ORDER BY cc.dimension_slice_id LIMIT 1) cc ON true
  INNER JOIN _timescaledb_catalog.dimension_slice ds ON ds.id=cc.dimension_slice_id
  INNER JOIN _timescaledb_catalog.dimension d ON ds.dimension_id = d.id
  INNER JOIN _timescaledb_catalog.hypertable ht ON d.hypertable_id = ht.id
ORDER BY ht.table_name, range_start, chunk;
       hypertable       |       chunk       |     range_start      
------------------------+-------------------+----------------------
 dimension_last         | _hyper_2_4_chunk  |      946684800000000
 dimension_last         | _hyper_2_5_chunk  |      946771200000000
 dimension_last         | _hyper_2_6_chunk  |      946857600000000
 dimension_last         | _hyper_2_7_chunk  |      946944000000000
 dimension_only         | _hyper_3_8_chunk  |      946684800000000
 dimension_only         | _hyper_3_9_chunk  |      946857600000000
 dimension_only         | _hyper_3_10_chunk |      947030400000000
 dimension_only         | _hyper_3_11_chunk |      947203200000000
 ht_dropped_columns     | _hyper_5_15_chunk |      946512000000000
 ht_dropped_columns     | _hyper_5_16_chunk |      947116800000000
 ht_dropped_columns     | _hyper_5_17_chunk |      947721600000000
 ht_dropped_columns     | _hyper_5_18_chunk |      948326400000000
 ht_dropped_columns     | _hyper_5_19_chunk |      948931200000000
 ht_missing_indexes     | _hyper_4_12_chunk |      946512000000000
 ht_missing_indexes     | _hyper_4_13_chunk |      947116800000000
 ht_missing_indexes     | _hyper_4_14_chunk |      947721600000000
 ordered_append_reverse | _hyper_1_3_chunk  |      946512000000000
 ordered_append_reverse | _hyper_1_2_chunk  |      947116800000000
 ordered_append_reverse | _hyper_1_1_chunk  |      947721600000000
 sortopt_test           | _hyper_8_55_chunk |      946512000000000
 sortopt_test           | _hyper_8_54_chunk |      947116800000000
 space2                 | _hyper_6_21_chunk | -9223372036854775808
 space2                 | _hyper_6_23_chunk | -9223372036854775808
 space2                 | _hyper_6_25_chunk | -9223372036854775808
 space2                 | _hyper_6_27_chunk | -9223372036854775808
 space2                 | _hyper_6_33_chunk | -9223372036854775808
 space2                 | _hyper_6_29_chunk |      946512000000000
 space2                 | _hyper_6_31_chunk |      946512000000000
 space2                 | _hyper_6_35_chunk |      946512000000000
 space2                 | _hyper_6_37_chunk |      946512000000000
 space2                 | _hyper_6_20_chunk |      947116800000000
 space2                 | _hyper_6_22_chunk |      947116800000000
 space2                 | _hyper_6_24_chunk |      947116800000000
 space2                 | _hyper_6_26_chunk |      947116800000000
 space2                 | _hyper_6_28_chunk |      947116800000000
 space2                 | _hyper_6_30_chunk |      947116800000000
 space2                 | _hyper_6_32_chunk |      947116800000000
 space2                 | _hyper_6_34_chunk |      947116800000000
 space2                 | _hyper_6_36_chunk |      947116800000000
 space3                 | _hyper_7_39_chunk | -9223372036854775808
 space3                 | _hyper_7_41_chunk | -9223372036854775808
 space3                 | _hyper_7_43_chunk | -9223372036854775808
 space3                 | _hyper_7_45_chunk | -9223372036854775808
 space3                 | _hyper_7_47_chunk | -9223372036854775808
 space3                 | _hyper_7_49_chunk | -9223372036854775808
 space3                 | _hyper_7_51_chunk | -9223372036854775808
 space3                 | _hyper_7_53_chunk |      946512000000000
 space3                 | _hyper_7_38_chunk |      947116800000000
 space3                 | _hyper_7_40_chunk |      947116800000000
 space3                 | _hyper_7_42_chunk |      947116800000000
 space3                 | _hyper_7_44_chunk |      947116800000000
 space3                 | _hyper_7_46_chunk |      947116800000000
 space3                 | _hyper_7_48_chunk |      947116800000000
 space3                 | _hyper_7_50_chunk |      947116800000000
 space3                 | _hyper_7_52_chunk |      947116800000000

-- test ASC for reverse ordered chunks
:PREFIX SELECT
  time, device_id, value
FROM ordered_append_reverse
ORDER BY time ASC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ordered_append_reverse (actual rows=1.00 loops=1)
         Order: ordered_append_reverse."time"
         ->  Index Scan Backward using _hyper_1_3_chunk_ordered_append_reverse_time_idx on _hyper_1_3_chunk (actual rows=1.00 loops=1)
         ->  Index Scan Backward using _hyper_1_2_chunk_ordered_append_reverse_time_idx on _hyper_1_2_chunk (never executed)
         ->  Index Scan Backward using _hyper_1_1_chunk_ordered_append_reverse_time_idx on _hyper_1_1_chunk (never executed)

-- test DESC for reverse ordered chunks
:PREFIX SELECT
  time, device_id, value
FROM ordered_append_reverse
ORDER BY time DESC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ordered_append_reverse (actual rows=1.00 loops=1)
         Order: ordered_append_reverse."time" DESC
         ->  Index Scan using _hyper_1_1_chunk_ordered_append_reverse_time_idx on _hyper_1_1_chunk (actual rows=1.00 loops=1)
         ->  Index Scan using _hyper_1_2_chunk_ordered_append_reverse_time_idx on _hyper_1_2_chunk (never executed)
         ->  Index Scan using _hyper_1_3_chunk_ordered_append_reverse_time_idx on _hyper_1_3_chunk (never executed)

-- test query with ORDER BY time_bucket, device_id
-- must not use ordered append
:PREFIX SELECT
  time_bucket('1d',time), device_id, name
FROM dimension_last
ORDER BY time_bucket('1d',time), device_id LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Sort (actual rows=1.00 loops=1)
         Sort Key: (time_bucket('@ 1 day'::interval, dimension_last."time")), dimension_last.device_id
         Sort Method: top-N heapsort 
         ->  Result (actual rows=5760.00 loops=1)
               ->  Append (actual rows=5760.00 loops=1)
                     ->  Seq Scan on _hyper_2_4_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_5_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_6_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_7_chunk (actual rows=1440.00 loops=1)

-- test query with ORDER BY date_trunc, device_id
-- must not use ordered append
:PREFIX SELECT
  date_trunc('day',time), device_id, name
FROM dimension_last
ORDER BY 1,2 LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Sort (actual rows=1.00 loops=1)
         Sort Key: (date_trunc('day'::text, dimension_last."time")), dimension_last.device_id
         Sort Method: top-N heapsort 
         ->  Result (actual rows=5760.00 loops=1)
               ->  Append (actual rows=5760.00 loops=1)
                     ->  Seq Scan on _hyper_2_4_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_5_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_6_chunk (actual rows=1440.00 loops=1)
                     ->  Seq Scan on _hyper_2_7_chunk (actual rows=1440.00 loops=1)

-- test with table with only dimension column
:PREFIX SELECT * FROM dimension_only ORDER BY time DESC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on dimension_only (actual rows=1.00 loops=1)
         Order: dimension_only."time" DESC
         ->  Index Only Scan using _hyper_3_11_chunk_dimension_only_time_idx on _hyper_3_11_chunk (actual rows=1.00 loops=1)
         ->  Index Only Scan using _hyper_3_10_chunk_dimension_only_time_idx on _hyper_3_10_chunk (never executed)
         ->  Index Only Scan using _hyper_3_9_chunk_dimension_only_time_idx on _hyper_3_9_chunk (never executed)
         ->  Index Only Scan using _hyper_3_8_chunk_dimension_only_time_idx on _hyper_3_8_chunk (never executed)

-- test LEFT JOIN against hypertable
:PREFIX_NO_ANALYZE SELECT *
FROM dimension_last
LEFT JOIN dimension_only USING (time)
ORDER BY dimension_last.time DESC
LIMIT 2;
--- QUERY PLAN ---
 Limit
   ->  Nested Loop Left Join
         Join Filter: (dimension_last."time" = dimension_only."time")
         ->  Custom Scan (ChunkAppend) on dimension_last
               Order: dimension_last."time" DESC
               ->  Index Scan using _hyper_2_7_chunk_dimension_last_time_idx on _hyper_2_7_chunk
               ->  Index Scan using _hyper_2_6_chunk_dimension_last_time_idx on _hyper_2_6_chunk
               ->  Index Scan using _hyper_2_5_chunk_dimension_last_time_idx on _hyper_2_5_chunk
               ->  Index Scan using _hyper_2_4_chunk_dimension_last_time_idx on _hyper_2_4_chunk
         ->  Materialize
               ->  Append
                     ->  Seq Scan on _hyper_3_11_chunk
                     ->  Seq Scan on _hyper_3_10_chunk
                     ->  Seq Scan on _hyper_3_9_chunk
                     ->  Seq Scan on _hyper_3_8_chunk

-- test INNER JOIN against non-hypertable
:PREFIX_NO_ANALYZE SELECT *
FROM dimension_last
INNER JOIN dimension_only USING (time)
ORDER BY dimension_last.time DESC
LIMIT 2;
--- QUERY PLAN ---
 Limit
   ->  Nested Loop
         ->  Custom Scan (ChunkAppend) on dimension_only
               Order: dimension_only."time" DESC
               ->  Index Only Scan using _hyper_3_11_chunk_dimension_only_time_idx on _hyper_3_11_chunk
               ->  Index Only Scan using _hyper_3_10_chunk_dimension_only_time_idx on _hyper_3_10_chunk
               ->  Index Only Scan using _hyper_3_9_chunk_dimension_only_time_idx on _hyper_3_9_chunk
               ->  Index Only Scan using _hyper_3_8_chunk_dimension_only_time_idx on _hyper_3_8_chunk
         ->  Append
               ->  Index Scan using _hyper_2_7_chunk_dimension_last_time_idx on _hyper_2_7_chunk
                     Index Cond: ("time" = dimension_only."time")
               ->  Index Scan using _hyper_2_6_chunk_dimension_last_time_idx on _hyper_2_6_chunk
                     Index Cond: ("time" = dimension_only."time")
               ->  Index Scan using _hyper_2_5_chunk_dimension_last_time_idx on _hyper_2_5_chunk
                     Index Cond: ("time" = dimension_only."time")
               ->  Index Scan using _hyper_2_4_chunk_dimension_last_time_idx on _hyper_2_4_chunk
                     Index Cond: ("time" = dimension_only."time")

-- test join against non-hypertable
:PREFIX SELECT *
FROM dimension_last
INNER JOIN devices USING(device_id)
ORDER BY dimension_last.time DESC
LIMIT 2;
--- QUERY PLAN ---
 Limit (actual rows=2.00 loops=1)
   ->  Nested Loop (actual rows=2.00 loops=1)
         Join Filter: (devices.device_id = dimension_last.device_id)
         ->  Custom Scan (ChunkAppend) on dimension_last (actual rows=2.00 loops=1)
               Order: dimension_last."time" DESC
               ->  Index Scan using _hyper_2_7_chunk_dimension_last_time_idx on _hyper_2_7_chunk (actual rows=2.00 loops=1)
               ->  Index Scan using _hyper_2_6_chunk_dimension_last_time_idx on _hyper_2_6_chunk (never executed)
               ->  Index Scan using _hyper_2_5_chunk_dimension_last_time_idx on _hyper_2_5_chunk (never executed)
               ->  Index Scan using _hyper_2_4_chunk_dimension_last_time_idx on _hyper_2_4_chunk (never executed)
         ->  Materialize (actual rows=1.00 loops=2)
               ->  Seq Scan on devices (actual rows=1.00 loops=1)

-- test hypertable with index missing on one chunk
:PREFIX SELECT
  time, device_id, value
FROM ht_missing_indexes
ORDER BY time ASC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ht_missing_indexes (actual rows=1.00 loops=1)
         Order: ht_missing_indexes."time"
         ->  Index Scan Backward using _hyper_4_12_chunk_ht_missing_indexes_time_idx on _hyper_4_12_chunk (actual rows=1.00 loops=1)
         ->  Sort (never executed)
               Sort Key: _hyper_4_13_chunk."time"
               ->  Seq Scan on _hyper_4_13_chunk (never executed)
         ->  Index Scan Backward using _hyper_4_14_chunk_ht_missing_indexes_time_idx on _hyper_4_14_chunk (never executed)

-- test hypertable with index missing on one chunk
-- and no data
:PREFIX SELECT
  time, device_id, value
FROM ht_missing_indexes
WHERE device_id = 2
ORDER BY time DESC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ht_missing_indexes (actual rows=1.00 loops=1)
         Order: ht_missing_indexes."time" DESC
         ->  Index Scan using _hyper_4_14_chunk_ht_missing_indexes_time_idx on _hyper_4_14_chunk (actual rows=1.00 loops=1)
               Filter: (device_id = 2)
               Rows Removed by Filter: 1
         ->  Sort (never executed)
               Sort Key: _hyper_4_13_chunk."time" DESC
               ->  Seq Scan on _hyper_4_13_chunk (never executed)
                     Filter: (device_id = 2)
         ->  Index Scan using _hyper_4_12_chunk_ht_missing_indexes_time_idx on _hyper_4_12_chunk (never executed)
               Filter: (device_id = 2)

-- test hypertable with index missing on one chunk
-- and no data
:PREFIX SELECT
  time, device_id, value
FROM ht_missing_indexes
WHERE time > '2000-01-07'
ORDER BY time LIMIT 10;
--- QUERY PLAN ---
 Limit (actual rows=10.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ht_missing_indexes (actual rows=10.00 loops=1)
         Order: ht_missing_indexes."time"
         ->  Sort (actual rows=10.00 loops=1)
               Sort Key: _hyper_4_13_chunk."time"
               Sort Method: top-N heapsort 
               ->  Seq Scan on _hyper_4_13_chunk (actual rows=24477.00 loops=1)
                     Filter: ("time" > 'Fri Jan 07 00:00:00 2000 PST'::timestamp with time zone)
                     Rows Removed by Filter: 5763
         ->  Index Scan Backward using _hyper_4_14_chunk_ht_missing_indexes_time_idx on _hyper_4_14_chunk (never executed)

-- test hypertable with dropped columns
:PREFIX SELECT
  time, device_id, value
FROM ht_dropped_columns
ORDER BY time ASC LIMIT 1;
--- QUERY PLAN ---
 Limit (actual rows=1.00 loops=1)
   ->  Custom Scan (ChunkAppend) on ht_dropped_columns (actual rows=1.00 loops=1)
         Order: ht_dropped_columns."time"
         ->  Index Scan Backward using _hyper_5_15_chunk_ht_dropped_columns_time_idx on _hyper_5_15_chunk (actual rows=1.00 loops=1)
         ->  Index Scan Backward using _hyper_5_16_chunk_ht_dropped_columns_time_idx on _hyper_5_16_chunk (never executed)
         ->  Index Scan Backward using _hyper_5_17_chunk_ht_dropped_columns_time_idx on _hyper_5_17_chunk (never executed)
         ->  Index Scan Backward using _hyper_5_18_chunk_ht_dropped_columns_time_idx on _hyper_5_18_chunk (never executed)
         ->  Index Scan Backward using _hyper_5_19_chunk_ht_dropped_columns_time_idx on _hyper_5_19_chunk (never executed)

-- test hypertable with dropped columns
:PREFIX SELECT
  time, device_id, value
FROM ht_dropped_columns
WHERE device_id = 1
ORDER BY time DESC;
--- QUERY PLAN ---
 Custom Scan (ChunkAppend) on ht_dropped_columns (actual rows=7205.00 loops=1)
   Order: ht_dropped_columns."time" DESC
   ->  Index Scan using _hyper_5_19_chunk_ht_dropped_columns_time_idx on _hyper_5_19_chunk (actual rows=1441.00 loops=1)
         Filter: (device_id = 1)
   ->  Index Scan using _hyper_5_18_chunk_ht_dropped_columns_time_idx on _hyper_5_18_chunk (actual rows=1441.00 loops=1)
         Filter: (device_id = 1)
   ->  Index Scan using _hyper_5_17_chunk_ht_dropped_columns_time_idx on _hyper_5_17_chunk (actual rows=1441.00 loops=1)
         Filter: (device_id = 1)
   ->  Index Scan using _hyper_5_16_chunk_ht_dropped_columns_time_idx on _hyper_5_16_chunk (actual rows=1441.00 loops=1)
         Filter: (device_id = 1)
   ->  Index Scan using _hyper_5_15_chunk_ht_dropped_columns_time_idx on _hyper_5_15_chunk (actual rows=1441.00 loops=1)
         Filter: (device_id = 1)

-- test hypertable with 2 space dimensions
:PREFIX SELECT
  time, device_id, value
FROM space2
ORDER BY time DESC;
--- QUERY PLAN ---
 Custom Scan (ChunkAppend) on space2 (actual rows=116649.00 loops=1)
   Order: space2."time" DESC
   ->  Merge Append (actual rows=56169.00 loops=1)
         Sort Key: space2."time" DESC
         ->  Index Scan using _hyper_6_36_chunk_space2_time_idx on _hyper_6_36_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_34_chunk_space2_time_idx on _hyper_6_34_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_32_chunk_space2_time_idx on _hyper_6_32_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_30_chunk_space2_time_idx on _hyper_6_30_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_28_chunk_space2_time_idx on _hyper_6_28_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_26_chunk_space2_time_idx on _hyper_6_26_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_24_chunk_space2_time_idx on _hyper_6_24_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_22_chunk_space2_time_idx on _hyper_6_22_chunk (actual rows=6241.00 loops=1)
         ->  Index Scan using _hyper_6_20_chunk_space2_time_idx on _hyper_6_20_chunk (actual rows=6241.00 loops=1)
   ->  Merge Append (actual rows=60480.00 loops=1)
         Sort Key: space2."time" DESC
         ->  Index Scan using _hyper_6_37_chunk_space2_time_idx on _hyper_6_37_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_35_chunk_space2_time_idx on _hyper_6_35_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_33_chunk_space2_time_idx on _hyper_6_33_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_31_chunk_space2_time_idx on _hyper_6_31_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_29_chunk_space2_time_idx on _hyper_6_29_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_27_chunk_space2_time_idx on _hyper_6_27_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_25_chunk_space2_time_idx on _hyper_6_25_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_23_chunk_space2_time_idx on _hyper_6_23_chunk (actual rows=6720.00 loops=1)
         ->  Index Scan using _hyper_6_21_chunk_space2_time_idx on _hyper_6_21_chunk (actual rows=6720.00 loops=1)

-- test hypertable with 3 space dimensions
:PREFIX SELECT
  time
FROM space3
ORDER BY time DESC;
--- QUERY PLAN ---
 Custom Scan (ChunkAppend) on space3 (actual rows=103688.00 loops=1)
   Order: space3."time" DESC
   ->  Merge Append (actual rows=49928.00 loops=1)
         Sort Key: space3."time" DESC
         ->  Index Only Scan using _hyper_7_52_chunk_space3_time_idx on _hyper_7_52_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_50_chunk_space3_time_idx on _hyper_7_50_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_48_chunk_space3_time_idx on _hyper_7_48_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_46_chunk_space3_time_idx on _hyper_7_46_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_44_chunk_space3_time_idx on _hyper_7_44_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_42_chunk_space3_time_idx on _hyper_7_42_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_40_chunk_space3_time_idx on _hyper_7_40_chunk (actual rows=6241.00 loops=1)
         ->  Index Only Scan using _hyper_7_38_chunk_space3_time_idx on _hyper_7_38_chunk (actual rows=6241.00 loops=1)
   ->  Merge Append (actual rows=53760.00 loops=1)
         Sort Key: space3."time" DESC
         ->  Index Only Scan using _hyper_7_53_chunk_space3_time_idx on _hyper_7_53_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_51_chunk_space3_time_idx on _hyper_7_51_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_49_chunk_space3_time_idx on _hyper_7_49_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_47_chunk_space3_time_idx on _hyper_7_47_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_45_chunk_space3_time_idx on _hyper_7_45_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_43_chunk_space3_time_idx on _hyper_7_43_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_41_chunk_space3_time_idx on _hyper_7_41_chunk (actual rows=6720.00 loops=1)
         ->  Index Only Scan using _hyper_7_39_chunk_space3_time_idx on _hyper_7_39_chunk (actual rows=6720.00 loops=1)

-- test COLLATION
-- cant be tested in our ci because alpine doesnt support locales
-- :PREFIX SELECT * FROM sortopt_test ORDER BY time, device COLLATE "en_US.utf8";
-- test NULLS FIRST
:PREFIX SELECT * FROM sortopt_test ORDER BY time, device NULLS FIRST;
--- QUERY PLAN ---
 Custom Scan (ChunkAppend) on sortopt_test (actual rows=12961.00 loops=1)
   Order: sortopt_test."time", sortopt_test.device NULLS FIRST
   ->  Index Only Scan using _hyper_8_55_chunk_time_device_nullsfirst on _hyper_8_55_chunk (actual rows=6720.00 loops=1)
   ->  Index Only Scan using _hyper_8_54_chunk_time_device_nullsfirst on _hyper_8_54_chunk (actual rows=6241.00 loops=1)

-- test NULLS LAST
:PREFIX SELECT * FROM sortopt_test ORDER BY time, device DESC NULLS LAST;
--- QUERY PLAN ---
 Custom Scan (ChunkAppend) on sortopt_test (actual rows=12961.00 loops=1)
   Order: sortopt_test."time", sortopt_test.device DESC NULLS LAST
   ->  Index Only Scan using _hyper_8_55_chunk_time_device_nullslast on _hyper_8_55_chunk (actual rows=6720.00 loops=1)
   ->  Index Only Scan using _hyper_8_54_chunk_time_device_nullslast on _hyper_8_54_chunk (actual rows=6241.00 loops=1)

--generate the results into two different files
\set ECHO errors
