Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 16fd03e

Browse files
committed
Allow parallel aggregate on string_agg and array_agg
This adds combine, serial and deserial functions for the array_agg() and string_agg() aggregate functions, thus allowing these aggregates to partake in partial aggregations. This allows both parallel aggregation to take place when these aggregates are present and also allows additional partition-wise aggregation plan shapes to include plans that require additional aggregation once the partially aggregated results from the partitions have been combined. Author: David Rowley Reviewed-by: Andres Freund, Tomas Vondra, Stephen Frost, Tom Lane Discussion: https://postgr.es/m/CAKJS1f9sx_6GTcvd6TMuZnNtCh0VhBzhX6FZqw17TgVFH-ga_A@mail.gmail.com
1 parent 5a3a953 commit 16fd03e

File tree

13 files changed

+1101
-28
lines changed

13 files changed

+1101
-28
lines changed

doc/src/sgml/func.sgml

+3-3
Original file line numberDiff line numberDiff line change
@@ -19746,7 +19746,7 @@ SELECT NULLIF(value, '(none)') ...
1974619746
<para>
1974719747
Collects all the input values, including nulls, into an array.
1974819748
</para></entry>
19749-
<entry>No</entry>
19749+
<entry>Yes</entry>
1975019750
</row>
1975119751

1975219752
<row>
@@ -19759,7 +19759,7 @@ SELECT NULLIF(value, '(none)') ...
1975919759
dimension. (The inputs must all have the same dimensionality, and
1976019760
cannot be empty or null.)
1976119761
</para></entry>
19762-
<entry>No</entry>
19762+
<entry>Yes</entry>
1976319763
</row>
1976419764

1976519765
<row>
@@ -20099,7 +20099,7 @@ SELECT NULLIF(value, '(none)') ...
2009920099
after the first is preceded by the
2010020100
corresponding <parameter>delimiter</parameter> (if it's not null).
2010120101
</para></entry>
20102-
<entry>No</entry>
20102+
<entry>Yes</entry>
2010320103
</row>
2010420104

2010520105
<row>

src/backend/optimizer/prep/prepagg.c

+24-4
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,30 @@ preprocess_aggref(Aggref *aggref, PlannerInfo *root)
305305
* functions; if not, we can't serialize partial-aggregation
306306
* results.
307307
*/
308-
else if (transinfo->aggtranstype == INTERNALOID &&
309-
(!OidIsValid(transinfo->serialfn_oid) ||
310-
!OidIsValid(transinfo->deserialfn_oid)))
311-
root->hasNonSerialAggs = true;
308+
else if (transinfo->aggtranstype == INTERNALOID)
309+
{
310+
311+
if (!OidIsValid(transinfo->serialfn_oid) ||
312+
!OidIsValid(transinfo->deserialfn_oid))
313+
root->hasNonSerialAggs = true;
314+
315+
/*
316+
* array_agg_serialize and array_agg_deserialize make use
317+
* of the aggregate non-byval input type's send and
318+
* receive functions. There's a chance that the type
319+
* being aggregated has one or both of these functions
320+
* missing. In this case we must not allow the
321+
* aggregate's serial and deserial functions to be used.
322+
* It would be nice not to have special case this and
323+
* instead provide some sort of supporting function within
324+
* the aggregate to do this, but for now, that seems like
325+
* overkill for this one case.
326+
*/
327+
if ((transinfo->serialfn_oid == F_ARRAY_AGG_SERIALIZE ||
328+
transinfo->deserialfn_oid == F_ARRAY_AGG_DESERIALIZE) &&
329+
!agg_args_support_sendreceive(aggref))
330+
root->hasNonSerialAggs = true;
331+
}
312332
}
313333
}
314334
agginfo->transno = transno;

src/backend/parser/parse_agg.c

+36-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*/
1515
#include "postgres.h"
1616

17+
#include "access/htup_details.h"
1718
#include "catalog/pg_aggregate.h"
1819
#include "catalog/pg_constraint.h"
1920
#include "catalog/pg_type.h"
@@ -28,7 +29,7 @@
2829
#include "rewrite/rewriteManip.h"
2930
#include "utils/builtins.h"
3031
#include "utils/lsyscache.h"
31-
32+
#include "utils/syscache.h"
3233

3334
typedef struct
3435
{
@@ -1947,6 +1948,40 @@ resolve_aggregate_transtype(Oid aggfuncid,
19471948
return aggtranstype;
19481949
}
19491950

1951+
/*
1952+
* agg_args_support_sendreceive
1953+
* Returns true if all non-byval of aggref's arg types have send and
1954+
* receive functions.
1955+
*/
1956+
bool
1957+
agg_args_support_sendreceive(Aggref *aggref)
1958+
{
1959+
ListCell *lc;
1960+
1961+
foreach(lc, aggref->args)
1962+
{
1963+
HeapTuple typeTuple;
1964+
Form_pg_type pt;
1965+
TargetEntry *tle = (TargetEntry *) lfirst(lc);
1966+
Oid type = exprType((Node *) tle->expr);
1967+
1968+
typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
1969+
if (!HeapTupleIsValid(typeTuple))
1970+
elog(ERROR, "cache lookup failed for type %u", type);
1971+
1972+
pt = (Form_pg_type) GETSTRUCT(typeTuple);
1973+
1974+
if (!pt->typbyval &&
1975+
(!OidIsValid(pt->typsend) || !OidIsValid(pt->typreceive)))
1976+
{
1977+
ReleaseSysCache(typeTuple);
1978+
return false;
1979+
}
1980+
ReleaseSysCache(typeTuple);
1981+
}
1982+
return true;
1983+
}
1984+
19501985
/*
19511986
* Create an expression tree for the transition function of an aggregate.
19521987
* This is needed so that polymorphic functions can be used within an

0 commit comments

Comments
 (0)