--
-- COLUMNAR_PARTITIONING
--
CREATE TABLE parent(ts timestamptz, i int, n numeric, s text)
  PARTITION BY RANGE (ts);
-- row partitions
CREATE TABLE p0 PARTITION OF parent
  FOR VALUES FROM ('2020-01-01') TO ('2020-02-01');
CREATE TABLE p1 PARTITION OF parent
  FOR VALUES FROM ('2020-02-01') TO ('2020-03-01');
CREATE TABLE p2 PARTITION OF parent
  FOR VALUES FROM ('2020-03-01') TO ('2020-04-01');
CREATE TABLE p3 PARTITION OF parent
  FOR VALUES FROM ('2020-04-01') TO ('2020-05-01');
INSERT INTO parent SELECT '2020-01-15', 10, 100, 'one thousand'
  FROM generate_series(1,100000);
INSERT INTO parent SELECT '2020-02-15', 20, 200, 'two thousand'
  FROM generate_series(1,100000);
INSERT INTO parent SELECT '2020-03-15', 30, 300, 'three thousand'
  FROM generate_series(1,100000);
INSERT INTO parent SELECT '2020-04-15', 30, 300, 'three thousand'
  FROM generate_series(1,100000);
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16
\gset
-- run parallel plans
\if :server_version_ge_16
SET debug_parallel_query = regress;
\else
SET force_parallel_mode = regress;
\endif
SET min_parallel_table_scan_size = 1;
SET parallel_tuple_cost = 0;
SET max_parallel_workers = 4;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent;
                        QUERY PLAN
---------------------------------------------------------------------
 Finalize Aggregate
   ->  Gather
         Workers Planned: 4
         ->  Partial Aggregate
               ->  Parallel Append
                     ->  Parallel Seq Scan on p0 parent_1
                     ->  Parallel Seq Scan on p1 parent_2
                     ->  Parallel Seq Scan on p2 parent_3
                     ->  Parallel Seq Scan on p3 parent_4
(9 rows)

SELECT count(*), sum(i), min(i), max(i) FROM parent;
 count  |   sum   | min | max
---------------------------------------------------------------------
 400000 | 9000000 |  10 |  30
(1 row)

-- set older partitions as columnar
ALTER TABLE p0 SET ACCESS METHOD columnar;
ALTER TABLE p1 SET ACCESS METHOD columnar;
ALTER TABLE p3 SET ACCESS METHOD columnar;
-- should also be parallel plan
EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent;
                            QUERY PLAN
---------------------------------------------------------------------
 Finalize Aggregate
   ->  Gather
         Workers Planned: 4
         ->  Partial Aggregate
               ->  Parallel Append
                     ->  Custom Scan (ColumnarScan) on p3 parent_4
                           Columnar Projected Columns: i
                     ->  Custom Scan (ColumnarScan) on p0 parent_1
                           Columnar Projected Columns: i
                     ->  Custom Scan (ColumnarScan) on p1 parent_2
                           Columnar Projected Columns: i
                     ->  Parallel Seq Scan on p2 parent_3
(12 rows)

SELECT count(*), sum(i), min(i), max(i) FROM parent;
 count  |   sum   | min | max
---------------------------------------------------------------------
 400000 | 9000000 |  10 |  30
(1 row)

-- and also parallel without custom scan
SET columnar.enable_custom_scan = FALSE;
EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent;
                        QUERY PLAN
---------------------------------------------------------------------
 Finalize Aggregate
   ->  Gather
         Workers Planned: 4
         ->  Partial Aggregate
               ->  Parallel Append
                     ->  Seq Scan on p3 parent_4
                     ->  Seq Scan on p0 parent_1
                     ->  Seq Scan on p1 parent_2
                     ->  Parallel Seq Scan on p2 parent_3
(9 rows)

SELECT count(*), sum(i), min(i), max(i) FROM parent;
 count  |   sum   | min | max
---------------------------------------------------------------------
 400000 | 9000000 |  10 |  30
(1 row)

SET columnar.enable_custom_scan TO DEFAULT;
\if :server_version_ge_16
SET debug_parallel_query TO DEFAULT;
\else
SET force_parallel_mode TO DEFAULT;
\endif
SET min_parallel_table_scan_size TO DEFAULT;
SET parallel_tuple_cost TO DEFAULT;
SET max_parallel_workers TO DEFAULT;
SET max_parallel_workers_per_gather TO DEFAULT;
CREATE INDEX parent_btree ON parent (n);
ANALYZE parent;
-- will use columnar custom scan on columnar partitions but index
-- scan on heap partition
EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent
WHERE ts > '2020-02-20' AND n < 5;
                                                              QUERY PLAN
---------------------------------------------------------------------
 Aggregate
   ->  Append
         ->  Custom Scan (ColumnarScan) on p1 parent_1
               Filter: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
               Columnar Projected Columns: ts, i, n
               Columnar Chunk Group Filters: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
         ->  Index Scan using p2_n_idx on p2 parent_2
               Index Cond: (n < '5'::numeric)
               Filter: (ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone)
         ->  Custom Scan (ColumnarScan) on p3 parent_3
               Filter: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
               Columnar Projected Columns: ts, i, n
               Columnar Chunk Group Filters: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
(13 rows)

BEGIN;
  SET LOCAL columnar.enable_custom_scan TO 'OFF';
  -- now that we disabled columnar custom scan, will use seq scan on columnar
  -- partitions since index scan is more expensive than seq scan too
  EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent
  WHERE ts > '2020-02-20' AND n < 5;
                                                   QUERY PLAN
---------------------------------------------------------------------
 Aggregate
   ->  Append
         ->  Seq Scan on p1 parent_1
               Filter: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
         ->  Index Scan using p2_n_idx on p2 parent_2
               Index Cond: (n < '5'::numeric)
               Filter: (ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone)
         ->  Seq Scan on p3 parent_3
               Filter: ((ts > 'Thu Feb 20 00:00:00 2020 PST'::timestamp with time zone) AND (n < '5'::numeric))
(9 rows)

ROLLBACK;
DROP TABLE parent;
--
-- Test inheritance
--
CREATE TABLE i_row(i int);
INSERT INTO i_row VALUES(100);
CREATE TABLE i_col(i int) USING columnar;
INSERT INTO i_col VALUES(200);
CREATE TABLE ij_row_row(j int) INHERITS(i_row);
INSERT INTO ij_row_row VALUES(300, 1000);
CREATE TABLE ij_row_col(j int) INHERITS(i_row) USING columnar;
INSERT INTO ij_row_col VALUES(400, 2000);
CREATE TABLE ij_col_row(j int) INHERITS(i_col);
INSERT INTO ij_col_row VALUES(500, 3000);
CREATE TABLE ij_col_col(j int) INHERITS(i_col) USING columnar;
INSERT INTO ij_col_col VALUES(600, 4000);
EXPLAIN (costs off) SELECT * FROM i_row;
                       QUERY PLAN
---------------------------------------------------------------------
 Append
   ->  Seq Scan on i_row i_row_1
   ->  Seq Scan on ij_row_row i_row_2
   ->  Custom Scan (ColumnarScan) on ij_row_col i_row_3
         Columnar Projected Columns: i
(5 rows)

SELECT * FROM i_row;
  i
---------------------------------------------------------------------
 100
 300
 400
(3 rows)

EXPLAIN (costs off) SELECT * FROM ONLY i_row;
    QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on i_row
(1 row)

SELECT * FROM ONLY i_row;
  i
---------------------------------------------------------------------
 100
(1 row)

EXPLAIN (costs off) SELECT * FROM i_col;
                       QUERY PLAN
---------------------------------------------------------------------
 Append
   ->  Custom Scan (ColumnarScan) on i_col i_col_1
         Columnar Projected Columns: i
   ->  Seq Scan on ij_col_row i_col_2
   ->  Custom Scan (ColumnarScan) on ij_col_col i_col_3
         Columnar Projected Columns: i
(6 rows)

SELECT * FROM i_col;
  i
---------------------------------------------------------------------
 200
 500
 600
(3 rows)

EXPLAIN (costs off) SELECT * FROM ONLY i_col;
             QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (ColumnarScan) on i_col
   Columnar Projected Columns: i
(2 rows)

SELECT * FROM ONLY i_col;
  i
---------------------------------------------------------------------
 200
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_row_row;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_row_row
(1 row)

SELECT * FROM ij_row_row;
  i  |  j
---------------------------------------------------------------------
 300 | 1000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_row_col;
                QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (ColumnarScan) on ij_row_col
   Columnar Projected Columns: i, j
(2 rows)

SELECT * FROM ij_row_col;
  i  |  j
---------------------------------------------------------------------
 400 | 2000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_col_row;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_col_row
(1 row)

SELECT * FROM ij_col_row;
  i  |  j
---------------------------------------------------------------------
 500 | 3000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_col_col;
                QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (ColumnarScan) on ij_col_col
   Columnar Projected Columns: i, j
(2 rows)

SELECT * FROM ij_col_col;
  i  |  j
---------------------------------------------------------------------
 600 | 4000
(1 row)

SET columnar.enable_custom_scan = FALSE;
EXPLAIN (costs off) SELECT * FROM i_row;
              QUERY PLAN
---------------------------------------------------------------------
 Append
   ->  Seq Scan on i_row i_row_1
   ->  Seq Scan on ij_row_row i_row_2
   ->  Seq Scan on ij_row_col i_row_3
(4 rows)

SELECT * FROM i_row;
  i
---------------------------------------------------------------------
 100
 300
 400
(3 rows)

EXPLAIN (costs off) SELECT * FROM ONLY i_row;
    QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on i_row
(1 row)

SELECT * FROM ONLY i_row;
  i
---------------------------------------------------------------------
 100
(1 row)

EXPLAIN (costs off) SELECT * FROM i_col;
              QUERY PLAN
---------------------------------------------------------------------
 Append
   ->  Seq Scan on i_col i_col_1
   ->  Seq Scan on ij_col_row i_col_2
   ->  Seq Scan on ij_col_col i_col_3
(4 rows)

SELECT * FROM i_col;
  i
---------------------------------------------------------------------
 200
 500
 600
(3 rows)

EXPLAIN (costs off) SELECT * FROM ONLY i_col;
    QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on i_col
(1 row)

SELECT * FROM ONLY i_col;
  i
---------------------------------------------------------------------
 200
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_row_row;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_row_row
(1 row)

SELECT * FROM ij_row_row;
  i  |  j
---------------------------------------------------------------------
 300 | 1000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_row_col;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_row_col
(1 row)

SELECT * FROM ij_row_col;
  i  |  j
---------------------------------------------------------------------
 400 | 2000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_col_row;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_col_row
(1 row)

SELECT * FROM ij_col_row;
  i  |  j
---------------------------------------------------------------------
 500 | 3000
(1 row)

EXPLAIN (costs off) SELECT * FROM ij_col_col;
       QUERY PLAN
---------------------------------------------------------------------
 Seq Scan on ij_col_col
(1 row)

SELECT * FROM ij_col_col;
  i  |  j
---------------------------------------------------------------------
 600 | 4000
(1 row)

SET columnar.enable_custom_scan TO DEFAULT;
-- remove the child table from the inheritance hierarchy table
ALTER TABLE ij_row_row NO INHERIT i_row;
DROP TABLE ij_row_row;
DROP TABLE i_row CASCADE;
NOTICE:  drop cascades to table ij_row_col
DROP TABLE i_col CASCADE;
NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to table ij_col_row
drop cascades to table ij_col_col
--
-- https://github.com/citusdata/citus/issues/5257
--
set default_table_access_method to columnar;
CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600);
CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);
INSERT INTO prt1 SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 2 = 0;
CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500);
CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600);
INSERT INTO prt2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 3 = 0;
SET enable_partitionwise_join to true;
EXPLAIN (costs off, timing off, summary off)
SELECT * FROM
  prt1 t1 LEFT JOIN LATERAL
  (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b)
    FROM prt1 t2
    JOIN prt2 t3 ON (t2.a = t3.b)
  ) ss
  ON t1.a = ss.t2a WHERE t1.b = 0
  ORDER BY t1.a;
                                QUERY PLAN
---------------------------------------------------------------------
 Sort
   Sort Key: t1.a
   ->  Append
         ->  Nested Loop Left Join
               ->  Custom Scan (ColumnarScan) on prt1_p1 t1_1
                     Filter: (b = 0)
                     Columnar Projected Columns: a, b, c
                     Columnar Chunk Group Filters: (b = 0)
               ->  Hash Join
                     Hash Cond: (t2_1.a = t3_1.b)
                     ->  Custom Scan (ColumnarScan) on prt1_p1 t2_1
                           Filter: (t1_1.a = a)
                           Columnar Projected Columns: a
                           Columnar Chunk Group Filters: (t1_1.a = a)
                     ->  Hash
                           ->  Custom Scan (ColumnarScan) on prt2_p1 t3_1
                                 Columnar Projected Columns: a, b
         ->  Nested Loop Left Join
               ->  Custom Scan (ColumnarScan) on prt1_p2 t1_2
                     Filter: (b = 0)
                     Columnar Projected Columns: a, b, c
                     Columnar Chunk Group Filters: (b = 0)
               ->  Hash Join
                     Hash Cond: (t2_2.a = t3_2.b)
                     ->  Custom Scan (ColumnarScan) on prt1_p2 t2_2
                           Filter: (t1_2.a = a)
                           Columnar Projected Columns: a
                           Columnar Chunk Group Filters: (t1_2.a = a)
                     ->  Hash
                           ->  Custom Scan (ColumnarScan) on prt2_p2 t3_2
                                 Columnar Projected Columns: a, b
         ->  Nested Loop Left Join
               ->  Custom Scan (ColumnarScan) on prt1_p3 t1_3
                     Filter: (b = 0)
                     Columnar Projected Columns: a, b, c
                     Columnar Chunk Group Filters: (b = 0)
               ->  Hash Join
                     Hash Cond: (t2_3.a = t3_3.b)
                     ->  Custom Scan (ColumnarScan) on prt1_p3 t2_3
                           Filter: (t1_3.a = a)
                           Columnar Projected Columns: a
                           Columnar Chunk Group Filters: (t1_3.a = a)
                     ->  Hash
                           ->  Custom Scan (ColumnarScan) on prt2_p3 t3_3
                                 Columnar Projected Columns: a, b
(45 rows)

SELECT * FROM
  prt1 t1 LEFT JOIN LATERAL
  (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b)
    FROM prt1 t2
    JOIN prt2 t3 ON (t2.a = t3.b)
  ) ss
  ON t1.a = ss.t2a WHERE t1.b = 0
  ORDER BY t1.a;
  a  | b |  c   | t2a | t3a | least
---------------------------------------------------------------------
   0 | 0 | 0000 |   0 |   0 |     0
  50 | 0 | 0050 |     |     |
 100 | 0 | 0100 |     |     |
 150 | 0 | 0150 | 150 |   0 |   150
 200 | 0 | 0200 |     |     |
 250 | 0 | 0250 |     |     |
 300 | 0 | 0300 | 300 |   0 |   300
 350 | 0 | 0350 |     |     |
 400 | 0 | 0400 |     |     |
 450 | 0 | 0450 | 450 |   0 |   450
 500 | 0 | 0500 |     |     |
 550 | 0 | 0550 |     |     |
(12 rows)

set default_table_access_method to default;
SET enable_partitionwise_join to default;
DROP TABLE prt1;
DROP TABLE prt2;
