-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
--TEST github issue 1650 character segment by column
CREATE TABLE test_chartab ( job_run_id INTEGER NOT NULL, mac_id CHAR(16) NOT NULL, rtt INTEGER NOT NULL, ts TIMESTAMP(3) NOT NULL );
SELECT create_hypertable('test_chartab', 'ts', chunk_time_interval => interval '1 day', migrate_data => true);
WARNING:  column type "timestamp without time zone" used for "ts" does not follow best practices
     create_hypertable     
---------------------------
 (1,public,test_chartab,t)

insert into test_chartab
values(8864, '0014070000006190' , 392 , '2019-12-14 02:52:05.863');
insert into test_chartab
values( 8864 , '0014070000011039' , 150 , '2019-12-14 02:52:05.863');
insert into test_chartab
values( 8864 , '001407000001DD2E' , 228 , '2019-12-14 02:52:05.863');
insert into test_chartab
values( 8890 , '001407000001DD2E' , 228 , '2019-12-20 02:52:05.863');
ALTER TABLE test_chartab SET (timescaledb.compress, timescaledb.compress_segmentby = 'mac_id', timescaledb.compress_orderby = 'ts DESC');
select * from test_chartab order by mac_id , ts limit 2;
 job_run_id |      mac_id      | rtt |              ts              
------------+------------------+-----+------------------------------
       8864 | 0014070000006190 | 392 | Sat Dec 14 02:52:05.863 2019
       8864 | 0014070000011039 | 150 | Sat Dec 14 02:52:05.863 2019

--compress the data and check --
SELECT compress_chunk('_timescaledb_internal._hyper_1_1_chunk');
             compress_chunk             
----------------------------------------
 _timescaledb_internal._hyper_1_1_chunk

select * from test_chartab order by mac_id , ts limit 2;
 job_run_id |      mac_id      | rtt |              ts              
------------+------------------+-----+------------------------------
       8864 | 0014070000006190 | 392 | Sat Dec 14 02:52:05.863 2019
       8864 | 0014070000011039 | 150 | Sat Dec 14 02:52:05.863 2019

SELECT compress_chunk('_timescaledb_internal._hyper_1_2_chunk');
             compress_chunk             
----------------------------------------
 _timescaledb_internal._hyper_1_2_chunk

select * from test_chartab order by mac_id , ts limit 2;
 job_run_id |      mac_id      | rtt |              ts              
------------+------------------+-----+------------------------------
       8864 | 0014070000006190 | 392 | Sat Dec 14 02:52:05.863 2019
       8864 | 0014070000011039 | 150 | Sat Dec 14 02:52:05.863 2019

VACUUM ANALYZE test_chartab;
-- test constraintawareappend sort node handling
SET work_mem to '16MB';
SET enable_hashagg TO false;
SET timescaledb.enable_chunkwise_aggregation TO false;
SET max_parallel_workers_per_gather = 0;
CREATE TABLE public.merge_sort (time timestamp NOT NULL, measure_id integer NOT NULL, device_id integer NOT NULL, value float);
SELECT create_hypertable('merge_sort', 'time');
WARNING:  column type "timestamp without time zone" used for "time" does not follow best practices
    create_hypertable    
-------------------------
 (3,public,merge_sort,t)

ALTER TABLE merge_sort SET (timescaledb.compress = true, timescaledb.compress_orderby = 'time', timescaledb.compress_segmentby = 'device_id, measure_id');
INSERT INTO merge_sort SELECT time, 1, 1, extract(epoch from time) * 0.001 FROM generate_series('2000-01-01'::timestamp,'2000-02-01'::timestamp,'5 sec'::interval) g1(time);
--compress first chunk
SELECT compress_chunk(ch) FROM show_chunks('merge_sort') ch LIMIT 1;
             compress_chunk             
----------------------------------------
 _timescaledb_internal._hyper_3_5_chunk

VACUUM ANALYZE merge_sort;
-- this should have a MergeAppend with children wrapped in Sort nodes
EXPLAIN (analyze,buffers off, costs off,timing off,summary off) SELECT
  last(time, time) as time,
  device_id,
  measure_id,
  last(value, time) AS value
FROM merge_sort
WHERE time < now()
GROUP BY 2, 3;
--- QUERY PLAN ---
 GroupAggregate (actual rows=1.00 loops=1)
   Group Key: merge_sort.device_id, merge_sort.measure_id
   ->  Custom Scan (ConstraintAwareAppend) (actual rows=535681.00 loops=1)
         Hypertable: merge_sort
         Chunks excluded during startup: 0
         ->  Merge Append (actual rows=535681.00 loops=1)
               Sort Key: merge_sort.device_id, merge_sort.measure_id
               ->  Custom Scan (ColumnarScan) on _hyper_3_5_chunk (actual rows=86400.00 loops=1)
                     Vectorized Filter: ("time" < "timestamp"(now()))
                     ->  Index Scan using compress_hyper_4_10_chunk_device_id_measure_id__ts_meta_min_idx on compress_hyper_4_10_chunk (actual rows=87.00 loops=1)
                           Index Cond: (_ts_meta_min_1 < now())
               ->  Sort (actual rows=120960.00 loops=1)
                     Sort Key: _hyper_3_6_chunk.device_id, _hyper_3_6_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_6_chunk (actual rows=120960.00 loops=1)
                           Filter: ("time" < now())
               ->  Sort (actual rows=120960.00 loops=1)
                     Sort Key: _hyper_3_7_chunk.device_id, _hyper_3_7_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_7_chunk (actual rows=120960.00 loops=1)
                           Filter: ("time" < now())
               ->  Sort (actual rows=120960.00 loops=1)
                     Sort Key: _hyper_3_8_chunk.device_id, _hyper_3_8_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_8_chunk (actual rows=120960.00 loops=1)
                           Filter: ("time" < now())
               ->  Sort (actual rows=86401.00 loops=1)
                     Sort Key: _hyper_3_9_chunk.device_id, _hyper_3_9_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_9_chunk (actual rows=86401.00 loops=1)
                           Filter: ("time" < now())

-- this should exclude the decompressed chunk
EXPLAIN (analyze,buffers off, costs off,timing off,summary off) SELECT
  last(time, time) as time,
  device_id,
  measure_id,
  last(value, time) AS value
FROM merge_sort
WHERE time > '2000-01-10'::text::timestamp
GROUP BY 2, 3;
--- QUERY PLAN ---
 GroupAggregate (actual rows=1.00 loops=1)
   Group Key: merge_sort.device_id, merge_sort.measure_id
   ->  Custom Scan (ConstraintAwareAppend) (actual rows=380160.00 loops=1)
         Hypertable: merge_sort
         Chunks excluded during startup: 1
         ->  Merge Append (actual rows=380160.00 loops=1)
               Sort Key: merge_sort.device_id, merge_sort.measure_id
               ->  Sort (actual rows=51839.00 loops=1)
                     Sort Key: _hyper_3_6_chunk.device_id, _hyper_3_6_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Index Scan using _hyper_3_6_chunk_merge_sort_time_idx on _hyper_3_6_chunk (actual rows=51839.00 loops=1)
                           Index Cond: ("time" > ('2000-01-10'::cstring)::timestamp without time zone)
               ->  Sort (actual rows=120960.00 loops=1)
                     Sort Key: _hyper_3_7_chunk.device_id, _hyper_3_7_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_7_chunk (actual rows=120960.00 loops=1)
                           Filter: ("time" > ('2000-01-10'::cstring)::timestamp without time zone)
               ->  Sort (actual rows=120960.00 loops=1)
                     Sort Key: _hyper_3_8_chunk.device_id, _hyper_3_8_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_8_chunk (actual rows=120960.00 loops=1)
                           Filter: ("time" > ('2000-01-10'::cstring)::timestamp without time zone)
               ->  Sort (actual rows=86401.00 loops=1)
                     Sort Key: _hyper_3_9_chunk.device_id, _hyper_3_9_chunk.measure_id
                     Sort Method: quicksort 
                     ->  Seq Scan on _hyper_3_9_chunk (actual rows=86401.00 loops=1)
                           Filter: ("time" > ('2000-01-10'::cstring)::timestamp without time zone)

RESET enable_hashagg;
RESET timescaledb.enable_chunkwise_aggregation;
RESET max_parallel_workers_per_gather;
RESET work_mem;
-- test if volatile function quals are applied to compressed chunks
CREATE FUNCTION check_equal_228( intval INTEGER) RETURNS BOOL
LANGUAGE PLPGSQL AS
$BODY$
DECLARE
    retval BOOL;
BEGIN
   IF intval = 228 THEN RETURN TRUE;
   ELSE RETURN FALSE;
   END IF;
END;
$BODY$;
-- the function cannot be pushed down to compressed chunk
-- but should be applied as a filter on decompresschunk
SELECT * from test_chartab
WHERE check_equal_228(rtt) ORDER BY ts;
 job_run_id |      mac_id      | rtt |              ts              
------------+------------------+-----+------------------------------
       8864 | 001407000001DD2E | 228 | Sat Dec 14 02:52:05.863 2019
       8890 | 001407000001DD2E | 228 | Fri Dec 20 02:52:05.863 2019

EXPLAIN (analyze,buffers off, costs off,timing off,summary off)
SELECT * from test_chartab
WHERE check_equal_228(rtt) and ts < '2019-12-15 00:00:00' order by ts;
--- QUERY PLAN ---
 Sort (actual rows=1.00 loops=1)
   Sort Key: test_chartab.ts
   Sort Method: quicksort 
   ->  Custom Scan (ChunkAppend) on test_chartab (actual rows=1.00 loops=1)
         Chunks excluded during startup: 0
         ->  Custom Scan (ColumnarScan) on _hyper_1_1_chunk (actual rows=1.00 loops=1)
               Filter: check_equal_228(rtt)
               Rows Removed by Filter: 2
               ->  Seq Scan on compress_hyper_2_3_chunk (actual rows=3.00 loops=1)

-- test pseudoconstant qual #3241
CREATE TABLE pseudo(time timestamptz NOT NULL);
SELECT create_hypertable('pseudo','time');
  create_hypertable  
---------------------
 (5,public,pseudo,t)

ALTER TABLE pseudo SET (timescaledb.compress);
INSERT INTO pseudo SELECT '2000-01-01';
SELECT compress_chunk(show_chunks('pseudo'));
             compress_chunk              
-----------------------------------------
 _timescaledb_internal._hyper_5_11_chunk

SELECT * FROM pseudo WHERE now() IS NOT NULL;
             time             
------------------------------
 Sat Jan 01 00:00:00 2000 PST

-- ensure needed decompression paths underneath a sort node
-- are not recycled by PostgreSQL
SET random_page_cost = 4.0;
DROP TABLE IF EXISTS options_data;
NOTICE:  table "options_data" does not exist, skipping
CREATE TABLE IF NOT EXISTS options_data (
    date            date NOT NULL,
    contract_code   text NOT NULL,
    expiry_code     text NOT NULL,
    option_type     character(1) NOT NULL,
    strike          real NOT NULL,
    price           double precision,
    source          text NOT NULL,
    meta            text
);
SELECT create_hypertable('options_data', 'date', chunk_time_interval => interval '1 day');
     create_hypertable     
---------------------------
 (7,public,options_data,t)

INSERT INTO options_data (date, contract_code, expiry_code, option_type, strike, price, source, meta)
SELECT
    date_series,
    'CONTRACT' || date_series::text,
    'EXPIRY' || date_series::text,
    CASE WHEN random() < 0.5 THEN 'C' ELSE 'P' END, -- Randomly choose 'C' or 'P' for option_type
   random() * 100, -- Random strike value between 0 and 100
   random() * 100, -- Random price value between 0 and 100
   'SOURCE' || date_series::text,
   'META' || date_series::text
FROM generate_series(
    '2023-12-01 00:00:00',
    '2023-12-05 00:00:00',
    INTERVAL '10 minute'
) AS date_series;
ALTER TABLE options_data SET (timescaledb.compress,
    timescaledb.compress_segmentby = 'contract_code, expiry_code, option_type, strike, source',
    timescaledb.compress_orderby = 'date DESC');
SELECT compress_chunk(ch) FROM show_chunks('options_data', older_than=> '2023-12-05') ch;
             compress_chunk              
-----------------------------------------
 _timescaledb_internal._hyper_7_13_chunk
 _timescaledb_internal._hyper_7_14_chunk
 _timescaledb_internal._hyper_7_15_chunk
 _timescaledb_internal._hyper_7_16_chunk

VACUUM ANALYZE options_data;
SELECT max(date) AS date FROM options_data WHERE contract_code='CONTRACT2023-12-03 04:00:00+01';
 date 
------
 

RESET random_page_cost;
