-- 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.
-- Exercise the Bitmap Heap Scan over the compressed chunk table. It requires
-- big tables with high selectivity OR queries on indexed columns, so it almost
-- doesn't happen in the normal tests.
\c :TEST_DBNAME :ROLE_SUPERUSER
-- helper function: float -> pseudorandom float [-0.5..0.5]
create or replace function mix(x anyelement) returns float8 as $$
    select hashfloat8(x::float8) / pow(2, 32)
$$ language sql;
set max_parallel_workers_per_gather = 0;
set enable_memoize to off;
create table bscan(ts int, s int, id int, payload int);
select create_hypertable('bscan', 'ts', chunk_time_interval => 500001);
 create_hypertable  
--------------------
 (1,public,bscan,t)

alter table bscan set (timescaledb.compress,
    timescaledb.compress_segmentby = 's',
    timescaledb.compress_orderby = 'id, ts');
insert into bscan
select ts,
    ts % 239 s,
    ts % 111721 id,
    (mix(ts % 1483) * 1483)::int payload
from generate_series(1, 1000000) ts;
-- tweak dataset to get whole number actual row results
update bscan set payload = -537, s = 1 where id in (1,2);
delete from bscan where payload = -537 and id not in (1,2);
create index on bscan(payload);
select count(compress_chunk(x)) from show_chunks('bscan') x;
 count 
-------
     2

vacuum full analyze bscan;
-- We have many conditions here, so it's less selective and the bitmap scan
-- overhead grows. This query should use Seq Scan.
explain (analyze, verbose, buffers off, costs off, timing off, summary off)
select * from bscan where id = 1 or id = 2 or id = 3 or id = 4 or id = 5
    or id = 6 or id = 7 or id = 8
;
--- QUERY PLAN ---
 Append (actual rows=72.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk (actual rows=40.00 loops=1)
         Output: _hyper_1_1_chunk.ts, _hyper_1_1_chunk.s, _hyper_1_1_chunk.id, _hyper_1_1_chunk.payload
         Vectorized Filter: ((_hyper_1_1_chunk.id = 1) OR (_hyper_1_1_chunk.id = 2) OR (_hyper_1_1_chunk.id = 3) OR (_hyper_1_1_chunk.id = 4) OR (_hyper_1_1_chunk.id = 5) OR (_hyper_1_1_chunk.id = 6) OR (_hyper_1_1_chunk.id = 7) OR (_hyper_1_1_chunk.id = 8))
         Rows Removed by Filter: 34960
         Batches Removed by Filter: 4
         Bulk Decompression: true
         ->  Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk (actual rows=35.00 loops=1)
               Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_2, compress_hyper_2_3_chunk._ts_meta_max_2, compress_hyper_2_3_chunk.ts, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.id, compress_hyper_2_3_chunk.regress-test-bloom_payload, compress_hyper_2_3_chunk.payload
               Filter: (((compress_hyper_2_3_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 2)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 3) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 3)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 4) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 4)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 5) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 5)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 6) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 6)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 7) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 7)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 8) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 8)))
               Rows Removed by Filter: 682
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_2_chunk (actual rows=32.00 loops=1)
         Output: _hyper_1_2_chunk.ts, _hyper_1_2_chunk.s, _hyper_1_2_chunk.id, _hyper_1_2_chunk.payload
         Vectorized Filter: ((_hyper_1_2_chunk.id = 1) OR (_hyper_1_2_chunk.id = 2) OR (_hyper_1_2_chunk.id = 3) OR (_hyper_1_2_chunk.id = 4) OR (_hyper_1_2_chunk.id = 5) OR (_hyper_1_2_chunk.id = 6) OR (_hyper_1_2_chunk.id = 7) OR (_hyper_1_2_chunk.id = 8))
         Rows Removed by Filter: 28968
         Batches Removed by Filter: 4
         Bulk Decompression: true
         ->  Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk (actual rows=29.00 loops=1)
               Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_2, compress_hyper_2_4_chunk._ts_meta_max_2, compress_hyper_2_4_chunk.ts, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.id, compress_hyper_2_4_chunk.regress-test-bloom_payload, compress_hyper_2_4_chunk.payload
               Filter: (((compress_hyper_2_4_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 2)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 3) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 3)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 4) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 4)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 5) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 5)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 6) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 6)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 7) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 7)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 8) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 8)))
               Rows Removed by Filter: 688

-- This should be Bitmap Heap Scan because we have an OR of highly selective
-- conditions.
explain (analyze, verbose, buffers off, costs off, timing off, summary off)
select * from bscan where id = 1 or id = 2
;
--- QUERY PLAN ---
 Append (actual rows=18.00 loops=1)
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk (actual rows=10.00 loops=1)
         Output: _hyper_1_1_chunk.ts, _hyper_1_1_chunk.s, _hyper_1_1_chunk.id, _hyper_1_1_chunk.payload
         Vectorized Filter: ((_hyper_1_1_chunk.id = 1) OR (_hyper_1_1_chunk.id = 2))
         Rows Removed by Filter: 4990
         Batches Removed by Filter: 4
         Bulk Decompression: true
         ->  Bitmap Heap Scan on _timescaledb_internal.compress_hyper_2_3_chunk (actual rows=5.00 loops=1)
               Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_2, compress_hyper_2_3_chunk._ts_meta_max_2, compress_hyper_2_3_chunk.ts, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.id, compress_hyper_2_3_chunk.regress-test-bloom_payload, compress_hyper_2_3_chunk.payload
               Recheck Cond: (((compress_hyper_2_3_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 2)))
               Heap Blocks: exact=5
               ->  BitmapOr (actual rows=0.00 loops=1)
                     ->  Bitmap Index Scan on compress_hyper_2_3_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                           Index Cond: ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 1))
                     ->  Bitmap Index Scan on compress_hyper_2_3_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                           Index Cond: ((compress_hyper_2_3_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_3_chunk._ts_meta_max_1 >= 2))
   ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_2_chunk (actual rows=8.00 loops=1)
         Output: _hyper_1_2_chunk.ts, _hyper_1_2_chunk.s, _hyper_1_2_chunk.id, _hyper_1_2_chunk.payload
         Vectorized Filter: ((_hyper_1_2_chunk.id = 1) OR (_hyper_1_2_chunk.id = 2))
         Rows Removed by Filter: 4992
         Batches Removed by Filter: 4
         Bulk Decompression: true
         ->  Bitmap Heap Scan on _timescaledb_internal.compress_hyper_2_4_chunk (actual rows=5.00 loops=1)
               Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_2, compress_hyper_2_4_chunk._ts_meta_max_2, compress_hyper_2_4_chunk.ts, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.id, compress_hyper_2_4_chunk.regress-test-bloom_payload, compress_hyper_2_4_chunk.payload
               Recheck Cond: (((compress_hyper_2_4_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 2)))
               Heap Blocks: exact=5
               ->  BitmapOr (actual rows=0.00 loops=1)
                     ->  Bitmap Index Scan on compress_hyper_2_4_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                           Index Cond: ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 1) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 1))
                     ->  Bitmap Index Scan on compress_hyper_2_4_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                           Index Cond: ((compress_hyper_2_4_chunk._ts_meta_min_1 <= 2) AND (compress_hyper_2_4_chunk._ts_meta_max_1 >= 2))

-- Also try a join with a Bitmap Heap Scan
set enable_mergejoin to off;
set enable_hashjoin to off;
explain (analyze, verbose, buffers off, costs off, timing off, summary off)
select * from bscan t1, bscan t2
where (t2.id = 1 or t2.id = 2)
    and t1.s = t2.s
    and t1.payload = -537;
--- QUERY PLAN ---
 Nested Loop (actual rows=324.00 loops=1)
   Output: t1.ts, t1.s, t1.id, t1.payload, t2.ts, t2.s, t2.id, t2.payload
   ->  Append (actual rows=18.00 loops=1)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk t2_1 (actual rows=10.00 loops=1)
               Output: t2_1.ts, t2_1.s, t2_1.id, t2_1.payload
               Vectorized Filter: ((t2_1.id = 1) OR (t2_1.id = 2))
               Rows Removed by Filter: 4990
               Batches Removed by Filter: 4
               Bulk Decompression: true
               ->  Bitmap Heap Scan on _timescaledb_internal.compress_hyper_2_3_chunk compress_hyper_2_3_chunk_1 (actual rows=5.00 loops=1)
                     Output: compress_hyper_2_3_chunk_1._ts_meta_count, compress_hyper_2_3_chunk_1.s, compress_hyper_2_3_chunk_1._ts_meta_min_2, compress_hyper_2_3_chunk_1._ts_meta_max_2, compress_hyper_2_3_chunk_1.ts, compress_hyper_2_3_chunk_1._ts_meta_min_1, compress_hyper_2_3_chunk_1._ts_meta_max_1, compress_hyper_2_3_chunk_1.id, compress_hyper_2_3_chunk_1.regress-test-bloom_payload, compress_hyper_2_3_chunk_1.payload
                     Recheck Cond: (((compress_hyper_2_3_chunk_1._ts_meta_min_1 <= 1) AND (compress_hyper_2_3_chunk_1._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_3_chunk_1._ts_meta_min_1 <= 2) AND (compress_hyper_2_3_chunk_1._ts_meta_max_1 >= 2)))
                     Heap Blocks: exact=5
                     ->  BitmapOr (actual rows=0.00 loops=1)
                           ->  Bitmap Index Scan on compress_hyper_2_3_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                                 Index Cond: ((compress_hyper_2_3_chunk_1._ts_meta_min_1 <= 1) AND (compress_hyper_2_3_chunk_1._ts_meta_max_1 >= 1))
                           ->  Bitmap Index Scan on compress_hyper_2_3_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                                 Index Cond: ((compress_hyper_2_3_chunk_1._ts_meta_min_1 <= 2) AND (compress_hyper_2_3_chunk_1._ts_meta_max_1 >= 2))
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_2_chunk t2_2 (actual rows=8.00 loops=1)
               Output: t2_2.ts, t2_2.s, t2_2.id, t2_2.payload
               Vectorized Filter: ((t2_2.id = 1) OR (t2_2.id = 2))
               Rows Removed by Filter: 4992
               Batches Removed by Filter: 4
               Bulk Decompression: true
               ->  Bitmap Heap Scan on _timescaledb_internal.compress_hyper_2_4_chunk compress_hyper_2_4_chunk_1 (actual rows=5.00 loops=1)
                     Output: compress_hyper_2_4_chunk_1._ts_meta_count, compress_hyper_2_4_chunk_1.s, compress_hyper_2_4_chunk_1._ts_meta_min_2, compress_hyper_2_4_chunk_1._ts_meta_max_2, compress_hyper_2_4_chunk_1.ts, compress_hyper_2_4_chunk_1._ts_meta_min_1, compress_hyper_2_4_chunk_1._ts_meta_max_1, compress_hyper_2_4_chunk_1.id, compress_hyper_2_4_chunk_1.regress-test-bloom_payload, compress_hyper_2_4_chunk_1.payload
                     Recheck Cond: (((compress_hyper_2_4_chunk_1._ts_meta_min_1 <= 1) AND (compress_hyper_2_4_chunk_1._ts_meta_max_1 >= 1)) OR ((compress_hyper_2_4_chunk_1._ts_meta_min_1 <= 2) AND (compress_hyper_2_4_chunk_1._ts_meta_max_1 >= 2)))
                     Heap Blocks: exact=5
                     ->  BitmapOr (actual rows=0.00 loops=1)
                           ->  Bitmap Index Scan on compress_hyper_2_4_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                                 Index Cond: ((compress_hyper_2_4_chunk_1._ts_meta_min_1 <= 1) AND (compress_hyper_2_4_chunk_1._ts_meta_max_1 >= 1))
                           ->  Bitmap Index Scan on compress_hyper_2_4_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx (actual rows=5.00 loops=1)
                                 Index Cond: ((compress_hyper_2_4_chunk_1._ts_meta_min_1 <= 2) AND (compress_hyper_2_4_chunk_1._ts_meta_max_1 >= 2))
   ->  Append (actual rows=18.00 loops=18)
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk t1_1 (actual rows=10.00 loops=18)
               Output: t1_1.ts, t1_1.s, t1_1.id, t1_1.payload
               Vectorized Filter: (t1_1.payload = '-537'::integer)
               Rows Removed by Filter: 990
               Bulk Decompression: true
               ->  Index Scan using compress_hyper_2_3_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx on _timescaledb_internal.compress_hyper_2_3_chunk (actual rows=1.00 loops=18)
                     Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_2, compress_hyper_2_3_chunk._ts_meta_max_2, compress_hyper_2_3_chunk.ts, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.id, compress_hyper_2_3_chunk.regress-test-bloom_payload, compress_hyper_2_3_chunk.payload
                     Index Cond: (compress_hyper_2_3_chunk.s = t2.s)
                     Filter: _timescaledb_functions.bloom1_contains(compress_hyper_2_3_chunk.regress-test-bloom_payload, '-537'::integer)
                     Rows Removed by Filter: 2
         ->  Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_2_chunk t1_2 (actual rows=8.00 loops=18)
               Output: t1_2.ts, t1_2.s, t1_2.id, t1_2.payload
               Vectorized Filter: (t1_2.payload = '-537'::integer)
               Rows Removed by Filter: 992
               Bulk Decompression: true
               ->  Index Scan using compress_hyper_2_4_chunk_s__ts_meta_min_1__ts_meta_max_1__t_idx on _timescaledb_internal.compress_hyper_2_4_chunk (actual rows=1.00 loops=18)
                     Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_2, compress_hyper_2_4_chunk._ts_meta_max_2, compress_hyper_2_4_chunk.ts, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.id, compress_hyper_2_4_chunk.regress-test-bloom_payload, compress_hyper_2_4_chunk.payload
                     Index Cond: (compress_hyper_2_4_chunk.s = t2.s)
                     Filter: _timescaledb_functions.bloom1_contains(compress_hyper_2_4_chunk.regress-test-bloom_payload, '-537'::integer)
                     Rows Removed by Filter: 2

;
reset enable_mergejoin;
reset enable_hashjoin;
