-- 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.
-- TEST1 count with integers
SHOW enable_partitionwise_aggregate;
 enable_partitionwise_aggregate 
--------------------------------
 off
(1 row)

SET enable_partitionwise_aggregate = on;
create table foo (a integer, b integer, c integer);
insert into foo values( 1 , 10 , 20);
insert into foo values( 1 , 11 , 20);
insert into foo values( 1 , 12 , 20);
insert into foo values( 1 , 13 , 20);
insert into foo values( 1 , 14 , 20);
insert into foo values( 2 , 14 , 20);
insert into foo values( 2 , 15 , 20);
insert into foo values( 2 , 16 , 20);
insert into foo values( 3 , 16 , 20);
create or replace view v1(a , partial)
as
 SELECT a, _timescaledb_internal.partialize_agg( count(b)) from foo group by a;
create table t1 as select * from v1;
select a, _timescaledb_internal.finalize_agg( 'count("any")', null, null, null, partial, cast('1' as int8) ) from t1
group by a order by a ;
 a | finalize_agg 
---+--------------
 1 |            5
 2 |            3
 3 |            1
(3 rows)

insert into t1 select * from t1;
select a, _timescaledb_internal.finalize_agg( 'count("any")', null, null, null, partial, cast('1' as int8) ) from t1
group by a order by a ;
 a | finalize_agg 
---+--------------
 1 |           10
 2 |            6
 3 |            2
(3 rows)

--TEST2 sum numeric and min on float--
drop table t1;
drop view v1;
drop table foo;
create table foo (a integer, b numeric , c float);
insert into foo values( 1 , 10 , 20);
insert into foo values( 1 , 20 , 19);
insert into foo values( 1 , 30 , 11.0);
insert into foo values( 1 , 40 , 200);
insert into foo values( 1 , 50 , -10);
insert into foo values( 2 , 10 , 20);
insert into foo values( 2 , 20 , 20);
insert into foo values( 2 , 30 , 20);
insert into foo values( 3 , 40 , 0);
create or replace view v1(a , partialb, partialminc)
as
 SELECT a,  _timescaledb_internal.partialize_agg( sum(b)) , _timescaledb_internal.partialize_agg( min(c)) from foo group by a;
create table t1 as select * from v1;
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, cast('1' as numeric) ) sumb, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
 a | sumb | minc 
---+------+------
 1 |  150 |  -10
 2 |   60 |   20
 3 |   40 |    0
(3 rows)

insert into foo values( 3, 0, -1);
insert into foo values( 5, 40, 10);
insert into foo values( 5, 40, 0);
--note that rows for 3 get added all over again + new row
--sum aggfnoid 2114, min aggfnoid is 2136 oid  numeric is 1700
insert into t1 select * from v1 where ( a = 3 ) or a = 5;
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, cast('1' as numeric) ) sumb, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
 a | sumb | minc 
---+------+------
 1 |  150 |  -10
 2 |   60 |   20
 3 |   80 |   -1
 5 |   80 |    0
(4 rows)

SET enable_partitionwise_aggregate = off;
--TEST3 sum with expressions
drop table t1;
drop view v1;
drop table foo;
create table foo (a integer, b numeric , c float);
insert into foo values( 1 , 10 , 20);
insert into foo values( 1 , 20 , 19);
insert into foo values( 1 , 30 , 11.0);
insert into foo values( 1 , 40 , 200);
insert into foo values( 1 , 50 , -10);
insert into foo values( 2 , 10 , 20);
insert into foo values( 2 , 20 , 20);
insert into foo values( 2 , 30 , 20);
insert into foo values( 3 , 40 , 0);
insert into foo values(10, NULL, NULL);
insert into foo values(11, NULL, NULL);
insert into foo values(11, NULL, NULL);
insert into foo values(12, NULL, NULL);
create or replace view v1(a , b, partialb, partialminc)
as
 SELECT a, b, _timescaledb_internal.partialize_agg( sum(b+c)) , _timescaledb_internal.partialize_agg( min(c)) from foo group by a, b ;
create table t1 as select * from v1;
insert into foo values( 3, 0, -1);
insert into foo values( 5, 40, 10);
insert into foo values( 5, 40, 0);
insert into foo values(12, 10, 20);
insert into t1 select * from v1 where ( a = 3 and b = 0 ) or a = 5 or (a = 12 and b = 10) ;
--results should match query: select a, sum(b+c), min(c) from foo group by a order by a;
--sum aggfnoid 2111 for float8, min aggfnoid is 2136 oid  numeric is 1700
select a, _timescaledb_internal.finalize_agg( 'sum(double precision)', null, null, null, partialb, null::float8 ) sumcd, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
 a  | sumcd | minc 
----+-------+------
  1 |   390 |  -10
  2 |   120 |   20
  3 |    39 |   -1
  5 |    90 |    0
 10 |       |     
 11 |       |     
 12 |    30 |   20
(7 rows)

insert into t1 select * from v1;
select a, _timescaledb_internal.finalize_agg( 'sum(double precision)', null, null, null, partialb, null::float8 ) sumcd, _timescaledb_internal.finalize_agg( 'min(double precision)', null, null, null, partialminc, cast('1' as float8) ) minc from t1 group by a order by a ;
 a  | sumcd | minc 
----+-------+------
  1 |   780 |  -10
  2 |   240 |   20
  3 |    78 |   -1
  5 |   180 |    0
 10 |       |     
 11 |       |     
 12 |    60 |   20
(7 rows)

-- TEST4 with collation (text), NULLS and timestamp --
drop table t1;
drop view v1;
drop table foo;
create table foo (a integer, b numeric , c text, d timestamptz, e bigint);
insert into foo values( 1 , 10 , 'hello', '2010-01-01 09:00:00-08', 10);
insert into foo values( 1 , 20 , 'abc', '2010-01-02 09:00:00-08', 20);
insert into foo values( 1 , 30 , 'abcd',  '2010-01-03 09:00:00-08', 30);
insert into foo values( 1 , 40 , 'abcde', NULL, 40);
insert into foo values( 1 , 50 , NULL,  '2010-01-01 09:00:00-08', 50);
--group with all values for c and d same
insert into foo values( 2 , 10 ,  'hello', '2010-01-01 09:00:00-08', 10);
insert into foo values( 2 , 20 , 'hello', '2010-01-01 09:00:00-08', 20);
insert into foo values( 2 , 30 , 'hello', '2010-01-01 09:00:00-08', 30);
--group with all values for c and d NULL
insert into foo values( 3 , 40 , NULL, NULL, 40);
insert into foo values( 3 , 50 , NULL, NULL, 50);
insert into foo values(11, NULL, NULL, NULL, NULL);
insert into foo values(11, NULL, 'hello', '2010-01-02 09:00:00-05', NULL);
--group with all values for c and d NULL and later add non-null.
insert into foo values(12, NULL, NULL, NULL, NULL);
create or replace view v1(a , b, partialb, partialc, partiald, partiale, partialf)
as
 SELECT a, b, _timescaledb_internal.partialize_agg(sum(b))
 , _timescaledb_internal.partialize_agg(min(c))
 , _timescaledb_internal.partialize_agg(max(d))
 , _timescaledb_internal.partialize_agg(stddev(b))
 , _timescaledb_internal.partialize_agg(stddev(e)) from foo group by a, b ;
create table t1 as select * from v1;
--sum 2114, collid 0, min(text) 2145, collid 100, max(ts) 2127
insert into foo values(12, 10, 'hello', '2010-01-02 09:00:00-05', 10);
insert into t1 select * from v1 where  (a = 12 and b = 10) ;
--select a, sum(b), min(c) , max(d), stddev(b), stddev(e) from foo group by a order by a;
--results should match above query
CREATE OR REPLACE VIEW vfinal(a , sumb, minc, maxd, stddevb, stddeve)
AS
select a, _timescaledb_internal.finalize_agg( 'sum(numeric)', null, null, null, partialb, null::numeric ) sumb
, _timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialc, null::text ) minc
, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) maxd
, _timescaledb_internal.finalize_agg( 'stddev(numeric)', null, null, null, partiale, null::numeric ) stddevb
, _timescaledb_internal.finalize_agg( 'stddev(int8)', null, null, null, partialf, null::numeric ) stddeve
from t1 group by a order by a ;
SELECT * FROM vfinal;
 a  | sumb | minc  |             maxd             |       stddevb       |       stddeve       
----+------+-------+------------------------------+---------------------+---------------------
  1 |  150 | abc   | Sun Jan 03 09:00:00 2010 PST | 15.8113883008418967 | 15.8113883008418967
  2 |   60 | hello | Fri Jan 01 09:00:00 2010 PST | 10.0000000000000000 | 10.0000000000000000
  3 |   90 |       |                              |  7.0710678118654752 |  7.0710678118654752
 11 |      | hello | Sat Jan 02 06:00:00 2010 PST |                     |                    
 12 |   10 | hello | Sat Jan 02 06:00:00 2010 PST |                     |                    
(5 rows)

CREATE TABLE vfinal_res AS SELECT * FROM vfinal;
-- overwrite partials with dumped binary values from PostrgeSQL 13 --
TRUNCATE TABLE t1;
\COPY t1 FROM data/partialize_finalize_data.csv WITH CSV HEADER
--repeat query to verify partial serialization sanitization works for versions PG >= 14
CREATE TABLE vfinal_dump_res AS SELECT * FROM vfinal;
-- compare results to verify there is no difference
(SELECT * FROM vfinal_res) EXCEPT (SELECT * FROM vfinal_dump_res);
 a | sumb | minc | maxd | stddevb | stddeve 
---+------+------+------+---------+---------
(0 rows)

--with having clause --
select a, b ,  _timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialc, null::text ) minc, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) maxd from t1  where b is not null group by a, b having _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partiald, null::timestamptz ) is not null order by a, b;
 a  | b  | minc  |             maxd             
----+----+-------+------------------------------
  1 | 10 | hello | Fri Jan 01 09:00:00 2010 PST
  1 | 20 | abc   | Sat Jan 02 09:00:00 2010 PST
  1 | 30 | abcd  | Sun Jan 03 09:00:00 2010 PST
  1 | 50 |       | Fri Jan 01 09:00:00 2010 PST
  2 | 10 | hello | Fri Jan 01 09:00:00 2010 PST
  2 | 20 | hello | Fri Jan 01 09:00:00 2010 PST
  2 | 30 | hello | Fri Jan 01 09:00:00 2010 PST
 12 | 10 | hello | Sat Jan 02 06:00:00 2010 PST
(8 rows)

--TEST5 test with TOAST data
drop view vfinal;
drop table t1;
drop view v1;
drop table foo;
create table foo( a integer, b timestamptz, toastval TEXT);
-- Set storage type to EXTERNAL to prevent PostgreSQL from compressing my
-- easily compressable string and instead store it with TOAST
ALTER TABLE foo ALTER COLUMN toastval SET STORAGE EXTERNAL;
SELECT count(*) FROM create_hypertable('foo', 'b');
NOTICE:  adding not-null constraint to column "b"
 count 
-------
     1
(1 row)

INSERT INTO foo VALUES( 1,  '2004-10-19 10:23:54', repeat('this must be over 2k. ', 1100));
INSERT INTO foo VALUES(1,  '2005-10-19 10:23:54', repeat('I am a tall big giraffe in the zoo.  ', 1100));
INSERT INTO foo values( 1, '2005-01-01 00:00:00+00', NULL);
INSERT INTO foo values( 2, '2005-01-01 00:00:00+00', NULL);
create or replace  view v1(a, partialb, partialtv) as select a, _timescaledb_internal.partialize_agg( max(b) ), _timescaledb_internal.partialize_agg( min(toastval)) from foo group by a;
EXPLAIN (VERBOSE, COSTS OFF)
create table t1 as select * from v1;
                                                                                    QUERY PLAN                                                                                     
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Partial HashAggregate
   Output: _hyper_1_1_chunk.a, _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_1_1_chunk.b)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_1_1_chunk.toastval))
   Group Key: _hyper_1_1_chunk.a
   ->  Append
         ->  Seq Scan on _timescaledb_internal._hyper_1_1_chunk
               Output: _hyper_1_1_chunk.a, _hyper_1_1_chunk.b, _hyper_1_1_chunk.toastval
         ->  Seq Scan on _timescaledb_internal._hyper_1_2_chunk
               Output: _hyper_1_2_chunk.a, _hyper_1_2_chunk.b, _hyper_1_2_chunk.toastval
         ->  Seq Scan on _timescaledb_internal._hyper_1_3_chunk
               Output: _hyper_1_3_chunk.a, _hyper_1_3_chunk.b, _hyper_1_3_chunk.toastval
(10 rows)

create table t1 as select * from v1;
insert into t1 select * from v1;
select a, _timescaledb_internal.finalize_agg( 'max(timestamp with time zone)', null, null, null, partialb, null::timestamptz ) maxb,
_timescaledb_internal.finalize_agg( 'min(text)', 'pg_catalog', 'default', null, partialtv, null::text ) = repeat('I am a tall big giraffe in the zoo.  ', 1100) mintv_equal
from t1 group by a order by a;
 a |             maxb             | mintv_equal 
---+------------------------------+-------------
 1 | Wed Oct 19 10:23:54 2005 PDT | t
 2 | Fri Dec 31 16:00:00 2004 PST | 
(2 rows)

--non top-level partials
with cte as (
   select a, _timescaledb_internal.partialize_agg(min(toastval)) tp from foo group by a
)
select length(tp) from cte;
 length 
--------
  40700
       
(2 rows)

select length(_timescaledb_internal.partialize_agg( min(toastval))) from foo group by a;
 length 
--------
  40700
       
(2 rows)

select length(_timescaledb_internal.partialize_agg(min(a+1))) from foo;
 length 
--------
      4
(1 row)

\set ON_ERROR_STOP 0
select length(_timescaledb_internal.partialize_agg(1+min(a))) from foo;
ERROR:  the input to partialize must be an aggregate
select length(_timescaledb_internal.partialize_agg(min(a)+min(a))) from foo;
ERROR:  the input to partialize must be an aggregate
--non-trivial HAVING clause not allowed with partialize_agg
select time_bucket('1 hour', b) as b, _timescaledb_internal.partialize_agg(avg(a))
from foo
group by 1
having avg(a) > 3;
ERROR:  cannot partialize aggregate with HAVING clause
--mixing partialized and non-partialized aggs is not allowed
select time_bucket('1 hour', b) as b, _timescaledb_internal.partialize_agg(avg(a)), sum(a)
from foo
group by 1;
ERROR:  cannot mix partialized and non-partialized aggregates in the same statement
\set ON_ERROR_STOP 1
--partializing works with HAVING when the planner can effectively
--reduce it. In this case to a simple filter.
select time_bucket('1 hour', b) as b, toastval, _timescaledb_internal.partialize_agg(avg(a))
from foo
group by b, toastval
having toastval LIKE 'does not exist';
 b | toastval | partialize_agg 
---+----------+----------------
(0 rows)

--
-- TEST FINALIZEFUNC_EXTRA
--
-- create special aggregate to test ffunc_extra
-- Raise warning with the actual type being passed in
CREATE OR REPLACE FUNCTION fake_ffunc(a int8, b int, x anyelement)
RETURNS anyelement AS $$
BEGIN
 RAISE WARNING 'type %', pg_typeof(x);
 RETURN x;
END;
$$
LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION fake_sfunc(a int8, b int, x anyelement)
RETURNS int8 AS $$
BEGIN
 RETURN b;
END; $$
LANGUAGE plpgsql;
CREATE AGGREGATE aggregate_to_test_ffunc_extra(int, anyelement) (
    SFUNC = fake_sfunc,
    STYPE = int8,
    COMBINEFUNC = int8pl,
    FINALFUNC = fake_ffunc,
    PARALLEL = SAFE,
    FINALFUNC_EXTRA
);
select aggregate_to_test_ffunc_extra(8, 'name'::text);
WARNING:  type text
 aggregate_to_test_ffunc_extra 
-------------------------------
 
(1 row)

\set ON_ERROR_STOP 0
--errors on wrong input type array
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, null, part, null::text) from cte;
ERROR:  cannot pass null input_type with FINALFUNC_EXTRA aggregates
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['a'::name, 'b'::name, 'c'::name]], part, null::text) from cte;
ERROR:  invalid input type array: expecting slices of size 2
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array[]::name[]]::name[], part, null::text) from cte;
ERROR:  invalid input type array: wrong number of dimensions
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[]::name[], part, null::text) from cte;
ERROR:  invalid input type array: wrong number of dimensions
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['public'::name, 'int'::name], array['public', 'text']], part, null::text) from cte;
ERROR:  invalid input type: public.int
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['public'::name, 'int4'::name], array['public', 'text']], part, null::text) from cte;
ERROR:  invalid input type: public.int4
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'text'], array['pg_catalog', 'text']], part, null::text) from cte;
ERROR:  invalid number of input types
select _timescaledb_internal.finalize_agg(NULL::text,NULL::name,NULL::name,NULL::_name,NULL::bytea,a) over () from foo;
ERROR:  finalize_agg_sfunc called in non-aggregate context
\set ON_ERROR_STOP 1
--make sure right type in warning and is null returns true
with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 'name'::text)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'text']], part, null::text) is null from cte;
WARNING:  type text
 ?column? 
----------
 t
(1 row)

with cte as (SELECT  _timescaledb_internal.partialize_agg(aggregate_to_test_ffunc_extra(8, 1::bigint)) as part)
select _timescaledb_internal.finalize_agg( 'aggregate_to_test_ffunc_extra(int, anyelement)', null, null, array[array['pg_catalog'::name, 'int4'::name], array['pg_catalog', 'int8']], part, null::text) is null from cte;
WARNING:  type bigint
 ?column? 
----------
 t
(1 row)

-- Issue 4922
CREATE TABLE issue4922 (
  time  TIMESTAMPTZ NOT NULL,
  value INTEGER
);
SELECT create_hypertable('issue4922', 'time');
   create_hypertable    
------------------------
 (2,public,issue4922,t)
(1 row)

-- helper function: integer -> pseudorandom integer [0..100].
CREATE OR REPLACE FUNCTION mix(x INTEGER) RETURNS INTEGER AS $$ SELECT (((hashint4(x) / (pow(2, 31) - 1) + 1) / 2) * 100)::INTEGER $$ LANGUAGE SQL;
INSERT INTO issue4922 (time, value)
SELECT '2022-01-01 00:00:00-03'::timestamptz + interval '1 year' * mix(x), mix(x)
FROM generate_series(1, 100000) x(x);
SET force_parallel_mode = 'on';
SET parallel_setup_cost = 0;
-- Materialize partials from execution of parallel query plan
EXPLAIN (VERBOSE, COSTS OFF)
  SELECT
    _timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
    _timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
    _timescaledb_internal.partialize_agg(min(value)) AS partial_min,
    _timescaledb_internal.partialize_agg(max(value)) AS partial_max,
    _timescaledb_internal.partialize_agg(count(*)) AS partial_count
  FROM public.issue4922;
                                                                                                                                                                                  QUERY PLAN                                                                                                                                                                                  
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Partial Aggregate
   Output: _timescaledb_internal.partialize_agg(PARTIAL sum(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL avg(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL count(*))
   ->  Gather
         Output: (PARTIAL sum(_hyper_2_4_chunk.value)), (PARTIAL avg(_hyper_2_4_chunk.value)), (PARTIAL min(_hyper_2_4_chunk.value)), (PARTIAL max(_hyper_2_4_chunk.value)), (PARTIAL count(*))
         Workers Planned: 2
         ->  Partial Aggregate
               Output: PARTIAL sum(_hyper_2_4_chunk.value), PARTIAL avg(_hyper_2_4_chunk.value), PARTIAL min(_hyper_2_4_chunk.value), PARTIAL max(_hyper_2_4_chunk.value), PARTIAL count(*)
               ->  Parallel Append
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_4_chunk
                           Output: _hyper_2_4_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_5_chunk
                           Output: _hyper_2_5_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_6_chunk
                           Output: _hyper_2_6_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_7_chunk
                           Output: _hyper_2_7_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_8_chunk
                           Output: _hyper_2_8_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_9_chunk
                           Output: _hyper_2_9_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_10_chunk
                           Output: _hyper_2_10_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_11_chunk
                           Output: _hyper_2_11_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_12_chunk
                           Output: _hyper_2_12_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_13_chunk
                           Output: _hyper_2_13_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_14_chunk
                           Output: _hyper_2_14_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_15_chunk
                           Output: _hyper_2_15_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_16_chunk
                           Output: _hyper_2_16_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_17_chunk
                           Output: _hyper_2_17_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_18_chunk
                           Output: _hyper_2_18_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_19_chunk
                           Output: _hyper_2_19_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_20_chunk
                           Output: _hyper_2_20_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_21_chunk
                           Output: _hyper_2_21_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_22_chunk
                           Output: _hyper_2_22_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_23_chunk
                           Output: _hyper_2_23_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_24_chunk
                           Output: _hyper_2_24_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_25_chunk
                           Output: _hyper_2_25_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_26_chunk
                           Output: _hyper_2_26_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_27_chunk
                           Output: _hyper_2_27_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_28_chunk
                           Output: _hyper_2_28_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_29_chunk
                           Output: _hyper_2_29_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_30_chunk
                           Output: _hyper_2_30_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_31_chunk
                           Output: _hyper_2_31_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_32_chunk
                           Output: _hyper_2_32_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_33_chunk
                           Output: _hyper_2_33_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_34_chunk
                           Output: _hyper_2_34_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_35_chunk
                           Output: _hyper_2_35_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_36_chunk
                           Output: _hyper_2_36_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_37_chunk
                           Output: _hyper_2_37_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_38_chunk
                           Output: _hyper_2_38_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_39_chunk
                           Output: _hyper_2_39_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_40_chunk
                           Output: _hyper_2_40_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_41_chunk
                           Output: _hyper_2_41_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_42_chunk
                           Output: _hyper_2_42_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_43_chunk
                           Output: _hyper_2_43_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_44_chunk
                           Output: _hyper_2_44_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_45_chunk
                           Output: _hyper_2_45_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_46_chunk
                           Output: _hyper_2_46_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_47_chunk
                           Output: _hyper_2_47_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_48_chunk
                           Output: _hyper_2_48_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_49_chunk
                           Output: _hyper_2_49_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_50_chunk
                           Output: _hyper_2_50_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_51_chunk
                           Output: _hyper_2_51_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_52_chunk
                           Output: _hyper_2_52_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_53_chunk
                           Output: _hyper_2_53_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_54_chunk
                           Output: _hyper_2_54_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_55_chunk
                           Output: _hyper_2_55_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_56_chunk
                           Output: _hyper_2_56_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_57_chunk
                           Output: _hyper_2_57_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_58_chunk
                           Output: _hyper_2_58_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_59_chunk
                           Output: _hyper_2_59_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_60_chunk
                           Output: _hyper_2_60_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_61_chunk
                           Output: _hyper_2_61_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_62_chunk
                           Output: _hyper_2_62_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_63_chunk
                           Output: _hyper_2_63_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_64_chunk
                           Output: _hyper_2_64_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_65_chunk
                           Output: _hyper_2_65_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_66_chunk
                           Output: _hyper_2_66_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_67_chunk
                           Output: _hyper_2_67_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_68_chunk
                           Output: _hyper_2_68_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_69_chunk
                           Output: _hyper_2_69_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_70_chunk
                           Output: _hyper_2_70_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_71_chunk
                           Output: _hyper_2_71_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_72_chunk
                           Output: _hyper_2_72_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_73_chunk
                           Output: _hyper_2_73_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_74_chunk
                           Output: _hyper_2_74_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_75_chunk
                           Output: _hyper_2_75_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_76_chunk
                           Output: _hyper_2_76_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_77_chunk
                           Output: _hyper_2_77_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_78_chunk
                           Output: _hyper_2_78_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_79_chunk
                           Output: _hyper_2_79_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_80_chunk
                           Output: _hyper_2_80_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_81_chunk
                           Output: _hyper_2_81_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_82_chunk
                           Output: _hyper_2_82_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_83_chunk
                           Output: _hyper_2_83_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_84_chunk
                           Output: _hyper_2_84_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_85_chunk
                           Output: _hyper_2_85_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_86_chunk
                           Output: _hyper_2_86_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_87_chunk
                           Output: _hyper_2_87_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_88_chunk
                           Output: _hyper_2_88_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_89_chunk
                           Output: _hyper_2_89_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_90_chunk
                           Output: _hyper_2_90_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_91_chunk
                           Output: _hyper_2_91_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_92_chunk
                           Output: _hyper_2_92_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_93_chunk
                           Output: _hyper_2_93_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_94_chunk
                           Output: _hyper_2_94_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_95_chunk
                           Output: _hyper_2_95_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_96_chunk
                           Output: _hyper_2_96_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_97_chunk
                           Output: _hyper_2_97_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_98_chunk
                           Output: _hyper_2_98_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_99_chunk
                           Output: _hyper_2_99_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_100_chunk
                           Output: _hyper_2_100_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_101_chunk
                           Output: _hyper_2_101_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_102_chunk
                           Output: _hyper_2_102_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_103_chunk
                           Output: _hyper_2_103_chunk.value
                     ->  Parallel Seq Scan on _timescaledb_internal._hyper_2_104_chunk
                           Output: _hyper_2_104_chunk.value
(210 rows)

CREATE MATERIALIZED VIEW issue4922_partials_parallel AS
  SELECT
    _timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
    _timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
    _timescaledb_internal.partialize_agg(min(value)) AS partial_min,
    _timescaledb_internal.partialize_agg(max(value)) AS partial_max,
    _timescaledb_internal.partialize_agg(count(*)) AS partial_count
  FROM public.issue4922;
-- Materialize partials from execution of non-parallel query plan
SET max_parallel_workers_per_gather = 0;
EXPLAIN (VERBOSE, COSTS OFF)
  SELECT
    _timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
    _timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
    _timescaledb_internal.partialize_agg(min(value)) AS partial_min,
    _timescaledb_internal.partialize_agg(max(value)) AS partial_max,
    _timescaledb_internal.partialize_agg(count(*)) AS partial_count
  FROM public.issue4922;
                                                                                                                                                                                  QUERY PLAN                                                                                                                                                                                  
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Partial Aggregate
   Output: _timescaledb_internal.partialize_agg(PARTIAL sum(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL avg(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL min(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL max(_hyper_2_4_chunk.value)), _timescaledb_internal.partialize_agg(PARTIAL count(*))
   ->  Append
         ->  Seq Scan on _timescaledb_internal._hyper_2_4_chunk
               Output: _hyper_2_4_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_5_chunk
               Output: _hyper_2_5_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_6_chunk
               Output: _hyper_2_6_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_7_chunk
               Output: _hyper_2_7_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_8_chunk
               Output: _hyper_2_8_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_9_chunk
               Output: _hyper_2_9_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_10_chunk
               Output: _hyper_2_10_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_11_chunk
               Output: _hyper_2_11_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_12_chunk
               Output: _hyper_2_12_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_13_chunk
               Output: _hyper_2_13_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_14_chunk
               Output: _hyper_2_14_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_15_chunk
               Output: _hyper_2_15_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_16_chunk
               Output: _hyper_2_16_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_17_chunk
               Output: _hyper_2_17_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_18_chunk
               Output: _hyper_2_18_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_19_chunk
               Output: _hyper_2_19_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_20_chunk
               Output: _hyper_2_20_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_21_chunk
               Output: _hyper_2_21_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_22_chunk
               Output: _hyper_2_22_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_23_chunk
               Output: _hyper_2_23_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_24_chunk
               Output: _hyper_2_24_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_25_chunk
               Output: _hyper_2_25_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_26_chunk
               Output: _hyper_2_26_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_27_chunk
               Output: _hyper_2_27_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_28_chunk
               Output: _hyper_2_28_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_29_chunk
               Output: _hyper_2_29_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_30_chunk
               Output: _hyper_2_30_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_31_chunk
               Output: _hyper_2_31_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_32_chunk
               Output: _hyper_2_32_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_33_chunk
               Output: _hyper_2_33_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_34_chunk
               Output: _hyper_2_34_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_35_chunk
               Output: _hyper_2_35_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_36_chunk
               Output: _hyper_2_36_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_37_chunk
               Output: _hyper_2_37_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_38_chunk
               Output: _hyper_2_38_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_39_chunk
               Output: _hyper_2_39_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_40_chunk
               Output: _hyper_2_40_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_41_chunk
               Output: _hyper_2_41_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_42_chunk
               Output: _hyper_2_42_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_43_chunk
               Output: _hyper_2_43_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_44_chunk
               Output: _hyper_2_44_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_45_chunk
               Output: _hyper_2_45_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_46_chunk
               Output: _hyper_2_46_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_47_chunk
               Output: _hyper_2_47_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_48_chunk
               Output: _hyper_2_48_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_49_chunk
               Output: _hyper_2_49_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_50_chunk
               Output: _hyper_2_50_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_51_chunk
               Output: _hyper_2_51_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_52_chunk
               Output: _hyper_2_52_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_53_chunk
               Output: _hyper_2_53_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_54_chunk
               Output: _hyper_2_54_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_55_chunk
               Output: _hyper_2_55_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_56_chunk
               Output: _hyper_2_56_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_57_chunk
               Output: _hyper_2_57_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_58_chunk
               Output: _hyper_2_58_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_59_chunk
               Output: _hyper_2_59_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_60_chunk
               Output: _hyper_2_60_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_61_chunk
               Output: _hyper_2_61_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_62_chunk
               Output: _hyper_2_62_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_63_chunk
               Output: _hyper_2_63_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_64_chunk
               Output: _hyper_2_64_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_65_chunk
               Output: _hyper_2_65_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_66_chunk
               Output: _hyper_2_66_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_67_chunk
               Output: _hyper_2_67_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_68_chunk
               Output: _hyper_2_68_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_69_chunk
               Output: _hyper_2_69_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_70_chunk
               Output: _hyper_2_70_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_71_chunk
               Output: _hyper_2_71_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_72_chunk
               Output: _hyper_2_72_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_73_chunk
               Output: _hyper_2_73_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_74_chunk
               Output: _hyper_2_74_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_75_chunk
               Output: _hyper_2_75_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_76_chunk
               Output: _hyper_2_76_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_77_chunk
               Output: _hyper_2_77_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_78_chunk
               Output: _hyper_2_78_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_79_chunk
               Output: _hyper_2_79_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_80_chunk
               Output: _hyper_2_80_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_81_chunk
               Output: _hyper_2_81_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_82_chunk
               Output: _hyper_2_82_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_83_chunk
               Output: _hyper_2_83_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_84_chunk
               Output: _hyper_2_84_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_85_chunk
               Output: _hyper_2_85_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_86_chunk
               Output: _hyper_2_86_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_87_chunk
               Output: _hyper_2_87_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_88_chunk
               Output: _hyper_2_88_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_89_chunk
               Output: _hyper_2_89_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_90_chunk
               Output: _hyper_2_90_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_91_chunk
               Output: _hyper_2_91_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_92_chunk
               Output: _hyper_2_92_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_93_chunk
               Output: _hyper_2_93_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_94_chunk
               Output: _hyper_2_94_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_95_chunk
               Output: _hyper_2_95_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_96_chunk
               Output: _hyper_2_96_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_97_chunk
               Output: _hyper_2_97_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_98_chunk
               Output: _hyper_2_98_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_99_chunk
               Output: _hyper_2_99_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_100_chunk
               Output: _hyper_2_100_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_101_chunk
               Output: _hyper_2_101_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_102_chunk
               Output: _hyper_2_102_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_103_chunk
               Output: _hyper_2_103_chunk.value
         ->  Seq Scan on _timescaledb_internal._hyper_2_104_chunk
               Output: _hyper_2_104_chunk.value
(205 rows)

CREATE MATERIALIZED VIEW issue4922_partials_non_parallel AS
  SELECT
    _timescaledb_internal.partialize_agg(sum(value)) AS partial_sum,
    _timescaledb_internal.partialize_agg(avg(value)) AS partial_avg,
    _timescaledb_internal.partialize_agg(min(value)) AS partial_min,
    _timescaledb_internal.partialize_agg(max(value)) AS partial_max,
    _timescaledb_internal.partialize_agg(count(*)) AS partial_count
  FROM public.issue4922;
RESET max_parallel_workers_per_gather;
-- partials should be the same in both parallel and non-parallel execution
SELECT * FROM issue4922_partials_parallel;
    partial_sum     |                                        partial_avg                                         | partial_min | partial_max |   partial_count    
--------------------+--------------------------------------------------------------------------------------------+-------------+-------------+--------------------
 \x00000000004c4fa9 | \x00000001000000000000001400000002000000010000000800000000000186a00000000800000000004c4fa9 | \x00000000  | \x00000064  | \x00000000000186a0
(1 row)

SELECT * FROM issue4922_partials_non_parallel;
    partial_sum     |                                        partial_avg                                         | partial_min | partial_max |   partial_count    
--------------------+--------------------------------------------------------------------------------------------+-------------+-------------+--------------------
 \x00000000004c4fa9 | \x00000001000000000000001400000002000000010000000800000000000186a00000000800000000004c4fa9 | \x00000000  | \x00000064  | \x00000000000186a0
(1 row)

-- Compare results from partial and non-partial query execution
SELECT
  sum(value),
  avg(value),
  min(value),
  max(value),
  count(*)
FROM issue4922;
   sum   |         avg         | min | max | count  
---------+---------------------+-----+-----+--------
 5001129 | 50.0112900000000000 |   0 | 100 | 100000
(1 row)

-- The results should be the EQUAL TO the previous query
SELECT
  _timescaledb_internal.finalize_agg('pg_catalog.sum(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_sum, NULL::bigint) AS sum,
  _timescaledb_internal.finalize_agg('pg_catalog.avg(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_avg, NULL::numeric) AS avg,
  _timescaledb_internal.finalize_agg('pg_catalog.min(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_min, NULL::integer) AS min,
  _timescaledb_internal.finalize_agg('pg_catalog.max(integer)'::text, NULL::name, NULL::name, '{{pg_catalog,int4}}'::name[], partial_max, NULL::integer) AS max,
  _timescaledb_internal.finalize_agg('pg_catalog.count()'::text, NULL::name, NULL::name, '{}'::name[], partial_count, NULL::bigint) AS count
FROM issue4922_partials_parallel;
   sum   |         avg         | min | max | count  
---------+---------------------+-----+-----+--------
 5001129 | 50.0112900000000000 |   0 | 100 | 100000
(1 row)