-- 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.
--
-- Setup
--
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE OR REPLACE FUNCTION ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(timeout INT = -1) RETURNS VOID
AS :MODULE_PATHNAME LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION ts_bgw_params_create() RETURNS VOID
AS :MODULE_PATHNAME LANGUAGE C VOLATILE;
\set WAIT_ON_JOB 0
\set IMMEDIATELY_SET_UNTIL 1
\set WAIT_FOR_OTHER_TO_ADVANCE 2
-- Remove any default jobs, e.g., telemetry
DELETE FROM _timescaledb_catalog.bgw_job WHERE TRUE;
TRUNCATE _timescaledb_internal.bgw_job_stat;
\c :TEST_DBNAME :ROLE_DEFAULT_PERM_USER
CREATE TABLE public.bgw_log(
    msg_no INT,
    mock_time BIGINT,
    application_name TEXT,
    msg TEXT
);
CREATE VIEW sorted_bgw_log AS
    SELECT * FROM bgw_log ORDER BY mock_time, application_name COLLATE "C", msg_no;
CREATE TABLE public.bgw_dsm_handle_store(
    handle BIGINT
);
INSERT INTO public.bgw_dsm_handle_store VALUES (0);
SELECT ts_bgw_params_create();
 ts_bgw_params_create 
----------------------
 

-----------------------------------
-- test retention policy runs for compressed hypertables --
-----------------------------------
CREATE TABLE test_retention_table(time timestamptz, drop_order int);
SELECT create_hypertable('test_retention_table', 'time', chunk_time_interval => INTERVAL '1 week');
         create_hypertable         
-----------------------------------
 (1,public,test_retention_table,t)

-- These inserts should create 5 different chunks
INSERT INTO test_retention_table VALUES (now() - INTERVAL '2 month',  4);
INSERT INTO test_retention_table VALUES (now(),                       5);
INSERT INTO test_retention_table VALUES (now() - INTERVAL '6 months', 2);
INSERT INTO test_retention_table VALUES (now() - INTERVAL '4 months', 3);
INSERT INTO test_retention_table VALUES (now() - INTERVAL '8 months', 1);
SELECT show_chunks('test_retention_table');
              show_chunks               
----------------------------------------
 _timescaledb_internal._hyper_1_1_chunk
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk

SELECT COUNT(*) FROM _timescaledb_catalog.chunk as c, _timescaledb_catalog.hypertable as ht where c.hypertable_id = ht.id and ht.table_name='test_retention_table';
 count 
-------
     5

SELECT count(*) FROM _timescaledb_catalog.bgw_job WHERE proc_schema = '_timescaledb_functions' AND proc_name = 'policy_retention';
 count 
-------
     0

SELECT add_retention_policy('test_retention_table', INTERVAL '4 months') as retention_job_id \gset
SELECT count(*) FROM _timescaledb_catalog.bgw_job WHERE proc_schema = '_timescaledb_functions' AND proc_name = 'policy_retention';
 count 
-------
     1

SELECT alter_job(:retention_job_id, schedule_interval => INTERVAL '1 second');
                                                                                        alter_job                                                                                         
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 (1000,"@ 1 sec","@ 5 mins",-1,"@ 5 mins",t,"{""drop_after"": ""@ 4 mons"", ""hypertable_id"": 1}",-infinity,_timescaledb_functions.policy_retention_check,f,,,"Retention Policy [1000]")

SELECT * FROM _timescaledb_catalog.bgw_job where id=:retention_job_id;
  id  |    application_name     | schedule_interval | max_runtime | max_retries | retry_period |      proc_schema       |    proc_name     |       owner       | scheduled | fixed_schedule | initial_start | hypertable_id |                     config                     |      check_schema      |       check_name       | timezone 
------+-------------------------+-------------------+-------------+-------------+--------------+------------------------+------------------+-------------------+-----------+----------------+---------------+---------------+------------------------------------------------+------------------------+------------------------+----------
 1000 | Retention Policy [1000] | @ 1 sec           | @ 5 mins    |          -1 | @ 5 mins     | _timescaledb_functions | policy_retention | default_perm_user | t         | f              |               |             1 | {"drop_after": "@ 4 mons", "hypertable_id": 1} | _timescaledb_functions | policy_retention_check | 

--turn on compression and compress all chunks
ALTER TABLE test_retention_table set (timescaledb.compress, timescaledb.compress_orderby = 'time DESC');
SELECT count(compress_chunk(ch)) FROM show_chunks('test_retention_table') ch;
 count 
-------
     5

--make sure same # of compressed and uncompressed chunks before policy
SELECT count(*) as count_chunks_uncompressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
WHERE hypertable.table_name like 'test_retention_table';
 count_chunks_uncompressed 
---------------------------
                         5

SELECT count(*) as count_chunks_compressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable comp_hyper ON (chunk.hypertable_id = comp_hyper.id)
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
WHERE uncomp_hyper.table_name like 'test_retention_table';
 count_chunks_compressed 
-------------------------
                       5

SELECT show_chunks('test_retention_table');
              show_chunks               
----------------------------------------
 _timescaledb_internal._hyper_1_1_chunk
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_3_chunk
 _timescaledb_internal._hyper_1_4_chunk
 _timescaledb_internal._hyper_1_5_chunk

SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(1000000);
 ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish 
------------------------------------------------------------
 

SELECT show_chunks('test_retention_table');
              show_chunks               
----------------------------------------
 _timescaledb_internal._hyper_1_1_chunk
 _timescaledb_internal._hyper_1_2_chunk
 _timescaledb_internal._hyper_1_4_chunk

--make sure same # of compressed and uncompressed chunks after policy, reduced by 2
SELECT count(*) as count_chunks_uncompressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
WHERE hypertable.table_name like 'test_retention_table';
 count_chunks_uncompressed 
---------------------------
                         3

SELECT count(*) as count_chunks_compressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable comp_hyper ON (chunk.hypertable_id = comp_hyper.id)
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
WHERE uncomp_hyper.table_name like 'test_retention_table';
 count_chunks_compressed 
-------------------------
                       3

------------------------------
-- Test reorder policy runs on compressed tables. Reorder policy job must skip compressed chunks
-- (see issue https://github.com/timescale/timescaledb/issues/1810).
-- More tests for reorder policy can be found at bgw_reorder_drop_chunks.sql
------------------------------
CREATE TABLE test_reorder_chunks_table(time int not null, chunk_id int);
CREATE INDEX test_reorder_chunks_table_time_idx ON test_reorder_chunks_table(time);
SELECT create_hypertable('test_reorder_chunks_table', 'time', chunk_time_interval => 1);
           create_hypertable            
----------------------------------------
 (3,public,test_reorder_chunks_table,t)

-- These inserts should create 6 different chunks
INSERT INTO test_reorder_chunks_table VALUES (1, 1);
INSERT INTO test_reorder_chunks_table VALUES (2, 2);
INSERT INTO test_reorder_chunks_table VALUES (3, 3);
INSERT INTO test_reorder_chunks_table VALUES (4, 4);
INSERT INTO test_reorder_chunks_table VALUES (5, 5);
INSERT INTO test_reorder_chunks_table VALUES (6, 6);
-- Enable compression
ALTER TABLE test_reorder_chunks_table set (timescaledb.compress, timescaledb.compress_orderby = 'time DESC');
-- Compress 2 chunks:
SELECT compress_chunk(show_chunks('test_reorder_chunks_table', newer_than => 2, older_than => 4));
             compress_chunk              
-----------------------------------------
 _timescaledb_internal._hyper_3_12_chunk
 _timescaledb_internal._hyper_3_13_chunk

-- make sure we have total of 6 chunks:
SELECT count(*) as count_chunks_uncompressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable hypertable ON (chunk.hypertable_id = hypertable.id)
WHERE hypertable.table_name like 'test_reorder_chunks_table';
 count_chunks_uncompressed 
---------------------------
                         6

-- and 2 compressed ones:
SELECT count(*) as count_chunks_compressed
FROM _timescaledb_catalog.chunk chunk
INNER JOIN _timescaledb_catalog.hypertable comp_hyper ON (chunk.hypertable_id = comp_hyper.id)
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
WHERE uncomp_hyper.table_name like 'test_reorder_chunks_table';
 count_chunks_compressed 
-------------------------
                       2

-- enable reorder policy
SELECT add_reorder_policy('test_reorder_chunks_table', 'test_reorder_chunks_table_time_idx') AS reorder_job_id \gset
-- nothing is clustered yet
SELECT indexrelid::regclass, indisclustered
    FROM pg_index
    WHERE indisclustered = true ORDER BY 1;
 indexrelid | indisclustered 
------------+----------------

-- run first time
SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25);
 ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish 
------------------------------------------------------------
 

SELECT job_id, last_run_success, total_runs, total_successes, total_failures, total_crashes
    FROM _timescaledb_internal.bgw_job_stat
    where job_id=:reorder_job_id;
 job_id | last_run_success | total_runs | total_successes | total_failures | total_crashes 
--------+------------------+------------+-----------------+----------------+---------------
   1001 | t                |          1 |               1 |              0 |             0

-- first chunk reordered
SELECT indexrelid::regclass, indisclustered
    FROM pg_index
    WHERE indisclustered = true ORDER BY 1;
                                 indexrelid                                 | indisclustered 
----------------------------------------------------------------------------+----------------
 _timescaledb_internal._hyper_3_11_chunk_test_reorder_chunks_table_time_idx | t

-- second call to scheduler
SELECT ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish(25);
 ts_bgw_db_scheduler_test_run_and_wait_for_scheduler_finish 
------------------------------------------------------------
 

SELECT job_id, last_run_success, total_runs, total_successes, total_failures, total_crashes
    FROM _timescaledb_internal.bgw_job_stat
    where job_id=:reorder_job_id;
 job_id | last_run_success | total_runs | total_successes | total_failures | total_crashes 
--------+------------------+------------+-----------------+----------------+---------------
   1001 | t                |          2 |               2 |              0 |             0

-- two chunks clustered, skips the compressed chunks
SELECT indexrelid::regclass, indisclustered
    FROM pg_index
    WHERE indisclustered = true ORDER BY 1;
                                 indexrelid                                 | indisclustered 
----------------------------------------------------------------------------+----------------
 _timescaledb_internal._hyper_3_11_chunk_test_reorder_chunks_table_time_idx | t
 _timescaledb_internal._hyper_3_14_chunk_test_reorder_chunks_table_time_idx | t

