-- 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 various corner cases of sorting.
create table t(x int, time timestamp, timetz timestamptz, int32 int4, int64 int8, s text);
select create_hypertable('t', 'x');
WARNING:  column type "timestamp without time zone" used for "time" does not follow best practices
 create_hypertable 
-------------------
 (1,public,t,t)

insert into t values
(1, '2022-01-01', '2023-01-01',  5, -13, 'a'),
(2, '2023-01-01', '2025-01-01',  1, -13, 'b'),
(3, '2024-01-01', '2021-01-01',  3, -16, 'd'),
(4, '2025-01-01', '2021-01-01', -2,  12, 'e'),
(5, '2021-01-01', '2026-01-01', -2,  14, 'e'),
(6, '2021-01-01', '2022-01-01', -4,  15, 'c')
;
alter table t set (timescaledb.compress, timescaledb.compress_segmentby='x', timescaledb.compress_orderby='time');
select compress_chunk(show_chunks('t')) \gset
set enable_sort to off;
set timescaledb.enable_decompression_sorted_merge to on;
set timescaledb.debug_require_batch_sorted_merge to 'require';
-- set enable_sort to on;
-- set timescaledb.enable_decompression_sorted_merge to off;
-- set timescaledb.debug_require_batch_sorted_merge to off;
select * from t order by time;
 x |           time           |            timetz            | int32 | int64 | s 
---+--------------------------+------------------------------+-------+-------+---
 5 | Fri Jan 01 00:00:00 2021 | Thu Jan 01 00:00:00 2026 PST |    -2 |    14 | e
 6 | Fri Jan 01 00:00:00 2021 | Sat Jan 01 00:00:00 2022 PST |    -4 |    15 | c
 1 | Sat Jan 01 00:00:00 2022 | Sun Jan 01 00:00:00 2023 PST |     5 |   -13 | a
 2 | Sun Jan 01 00:00:00 2023 | Wed Jan 01 00:00:00 2025 PST |     1 |   -13 | b
 3 | Mon Jan 01 00:00:00 2024 | Fri Jan 01 00:00:00 2021 PST |     3 |   -16 | d
 4 | Wed Jan 01 00:00:00 2025 | Fri Jan 01 00:00:00 2021 PST |    -2 |    12 | e

-- Test the fix for #7975: batch sort merge over eligible OpExpr and FuncExpr
select time::timestamptz + interval '1 second' from t order by time::timestamptz + interval '1 second';
           ?column?           
------------------------------
 Fri Jan 01 00:00:01 2021 PST
 Fri Jan 01 00:00:01 2021 PST
 Sat Jan 01 00:00:01 2022 PST
 Sun Jan 01 00:00:01 2023 PST
 Mon Jan 01 00:00:01 2024 PST
 Wed Jan 01 00:00:01 2025 PST

select time + interval '1 second' from t order by time + interval '1 second';
         ?column?         
--------------------------
 Fri Jan 01 00:00:01 2021
 Fri Jan 01 00:00:01 2021
 Sat Jan 01 00:00:01 2022
 Sun Jan 01 00:00:01 2023
 Mon Jan 01 00:00:01 2024
 Wed Jan 01 00:00:01 2025

select decompress_chunk(show_chunks('t')) \gset
alter table t set (timescaledb.compress, timescaledb.compress_segmentby='x', timescaledb.compress_orderby='timetz,time');
select compress_chunk(show_chunks('t')) \gset
select * from t order by timetz, time;
 x |           time           |            timetz            | int32 | int64 | s 
---+--------------------------+------------------------------+-------+-------+---
 3 | Mon Jan 01 00:00:00 2024 | Fri Jan 01 00:00:00 2021 PST |     3 |   -16 | d
 4 | Wed Jan 01 00:00:00 2025 | Fri Jan 01 00:00:00 2021 PST |    -2 |    12 | e
 6 | Fri Jan 01 00:00:00 2021 | Sat Jan 01 00:00:00 2022 PST |    -4 |    15 | c
 1 | Sat Jan 01 00:00:00 2022 | Sun Jan 01 00:00:00 2023 PST |     5 |   -13 | a
 2 | Sun Jan 01 00:00:00 2023 | Wed Jan 01 00:00:00 2025 PST |     1 |   -13 | b
 5 | Fri Jan 01 00:00:00 2021 | Thu Jan 01 00:00:00 2026 PST |    -2 |    14 | e

select timetz::timestamp + interval '1 second' from t order by timetz::timestamp + interval '1 second';
         ?column?         
--------------------------
 Fri Jan 01 00:00:01 2021
 Fri Jan 01 00:00:01 2021
 Sat Jan 01 00:00:01 2022
 Sun Jan 01 00:00:01 2023
 Wed Jan 01 00:00:01 2025
 Thu Jan 01 00:00:01 2026

select timetz + interval '1 second' from t order by timetz + interval '1 second';
           ?column?           
------------------------------
 Fri Jan 01 00:00:01 2021 PST
 Fri Jan 01 00:00:01 2021 PST
 Sat Jan 01 00:00:01 2022 PST
 Sun Jan 01 00:00:01 2023 PST
 Wed Jan 01 00:00:01 2025 PST
 Thu Jan 01 00:00:01 2026 PST

select decompress_chunk(show_chunks('t')) \gset
alter table t set (timescaledb.compress, timescaledb.compress_segmentby='x', timescaledb.compress_orderby='int32,timetz,time');
select compress_chunk(show_chunks('t')) \gset
select * from t order by int32, timetz, time;
 x |           time           |            timetz            | int32 | int64 | s 
---+--------------------------+------------------------------+-------+-------+---
 6 | Fri Jan 01 00:00:00 2021 | Sat Jan 01 00:00:00 2022 PST |    -4 |    15 | c
 4 | Wed Jan 01 00:00:00 2025 | Fri Jan 01 00:00:00 2021 PST |    -2 |    12 | e
 5 | Fri Jan 01 00:00:00 2021 | Thu Jan 01 00:00:00 2026 PST |    -2 |    14 | e
 2 | Sun Jan 01 00:00:00 2023 | Wed Jan 01 00:00:00 2025 PST |     1 |   -13 | b
 3 | Mon Jan 01 00:00:00 2024 | Fri Jan 01 00:00:00 2021 PST |     3 |   -16 | d
 1 | Sat Jan 01 00:00:00 2022 | Sun Jan 01 00:00:00 2023 PST |     5 |   -13 | a

select int32 + 1 from t order by int32 + 1;
 ?column? 
----------
       -3
       -1
       -1
        2
        4
        6

-- Sort Merge not used because only last Order By expression can be sort-transformed, not both of them
\set ON_ERROR_STOP 0
select int32 + 1, timetz  + interval '1 second' from t order by int32 + 1, timetz  + interval '1 second';
ERROR:  debug: batch sorted merge is required but not possible at planning time
\set ON_ERROR_STOP 1
select decompress_chunk(show_chunks('t')) \gset
alter table t set (timescaledb.compress, timescaledb.compress_segmentby='x', timescaledb.compress_orderby='int64,int32,timetz,time');
select compress_chunk(show_chunks('t')) \gset
select * from t order by int64, int32, timetz, time;
 x |           time           |            timetz            | int32 | int64 | s 
---+--------------------------+------------------------------+-------+-------+---
 3 | Mon Jan 01 00:00:00 2024 | Fri Jan 01 00:00:00 2021 PST |     3 |   -16 | d
 2 | Sun Jan 01 00:00:00 2023 | Wed Jan 01 00:00:00 2025 PST |     1 |   -13 | b
 1 | Sat Jan 01 00:00:00 2022 | Sun Jan 01 00:00:00 2023 PST |     5 |   -13 | a
 4 | Wed Jan 01 00:00:00 2025 | Fri Jan 01 00:00:00 2021 PST |    -2 |    12 | e
 5 | Fri Jan 01 00:00:00 2021 | Thu Jan 01 00:00:00 2026 PST |    -2 |    14 | e
 6 | Fri Jan 01 00:00:00 2021 | Sat Jan 01 00:00:00 2022 PST |    -4 |    15 | c

-- Both sides of OpExpr have to be of the same type for sort_transform to work
select int64 + 1 from t order by int64 + 1::int8;
 ?column? 
----------
      -15
      -12
      -12
       13
       15
       16

-- Batch sort merge won't be used as sides of OpExpr are of different types (int8 vs int4)
\set ON_ERROR_STOP 0
select int64 + 1 from t order by int64 + 1;
ERROR:  debug: batch sorted merge is required but not possible at planning time
\set ON_ERROR_STOP 1
select decompress_chunk(show_chunks('t')) \gset
alter table t set (timescaledb.compress, timescaledb.compress_segmentby='x', timescaledb.compress_orderby='s,int32,time desc');
select compress_chunk(show_chunks('t')) \gset
select * from t order by s, int32, time desc;
 x |           time           |            timetz            | int32 | int64 | s 
---+--------------------------+------------------------------+-------+-------+---
 1 | Sat Jan 01 00:00:00 2022 | Sun Jan 01 00:00:00 2023 PST |     5 |   -13 | a
 2 | Sun Jan 01 00:00:00 2023 | Wed Jan 01 00:00:00 2025 PST |     1 |   -13 | b
 6 | Fri Jan 01 00:00:00 2021 | Sat Jan 01 00:00:00 2022 PST |    -4 |    15 | c
 3 | Mon Jan 01 00:00:00 2024 | Fri Jan 01 00:00:00 2021 PST |     3 |   -16 | d
 4 | Wed Jan 01 00:00:00 2025 | Fri Jan 01 00:00:00 2021 PST |    -2 |    12 | e
 5 | Fri Jan 01 00:00:00 2021 | Thu Jan 01 00:00:00 2026 PST |    -2 |    14 | e

-- Batch sort merge won't be used as only Int and Date/Time types are allowed in OpExpr
\set ON_ERROR_STOP 0
select s||'1' from t order by s||'1';
ERROR:  debug: batch sorted merge is required but not possible at planning time
\set ON_ERROR_STOP 1
