diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index b15d9b152ef..be88909da22 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -1961,7 +1961,7 @@ resolve_aggregate_transtype(Oid aggfuncid, /* * agg_args_support_sendreceive - * Returns true if all non-byval of aggref's arg types have send and + * Returns true if all non-byval types of aggref's args have send and * receive functions. */ bool @@ -1976,6 +1976,15 @@ agg_args_support_sendreceive(Aggref *aggref) TargetEntry *tle = (TargetEntry *) lfirst(lc); Oid type = exprType((Node *) tle->expr); + /* + * RECORD is a special case: it has typsend/typreceive functions, but + * record_recv only works if passed the correct typmod to identify the + * specific anonymous record type. array_agg_deserialize cannot do + * that, so we have to disclaim support for the case. + */ + if (type == RECORDOID) + return false; + typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type)); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", type); diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index 1c1ca7573ad..30af83f23cc 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -2033,8 +2033,8 @@ explain (costs off) select * from v_pagg_test order by y; -> Parallel Seq Scan on pagg_test (13 rows) -set max_parallel_workers_per_gather = 0; -- Ensure results are the same without parallel aggregation. +set max_parallel_workers_per_gather = 0; select * from v_pagg_test order by y; y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ---+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- @@ -2050,6 +2050,24 @@ select * from v_pagg_test order by y; 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 (10 rows) +-- Check that we don't fail on anonymous record types. +set max_parallel_workers_per_gather = 2; +explain (costs off) +select array_dims(array_agg(s)) from (select * from pagg_test) s; + QUERY PLAN +-------------------------------------------- + Aggregate + -> Gather + Workers Planned: 2 + -> Parallel Seq Scan on pagg_test +(4 rows) + +select array_dims(array_agg(s)) from (select * from pagg_test) s; + array_dims +------------ + [1:5000] +(1 row) + -- Clean up reset max_parallel_workers_per_gather; reset bytea_output; diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 1a18ca3d8fe..675b23add59 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -805,11 +805,16 @@ select * from v_pagg_test order by y; -- Ensure parallel aggregation is actually being used. explain (costs off) select * from v_pagg_test order by y; -set max_parallel_workers_per_gather = 0; - -- Ensure results are the same without parallel aggregation. +set max_parallel_workers_per_gather = 0; select * from v_pagg_test order by y; +-- Check that we don't fail on anonymous record types. +set max_parallel_workers_per_gather = 2; +explain (costs off) +select array_dims(array_agg(s)) from (select * from pagg_test) s; +select array_dims(array_agg(s)) from (select * from pagg_test) s; + -- Clean up reset max_parallel_workers_per_gather; reset bytea_output;