Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 16fd03e

Browse filesBrowse 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
Copy full SHA for 16fd03e

File tree

13 files changed

+1101
-28
lines changed
Filter options

13 files changed

+1101
-28
lines changed

‎doc/src/sgml/func.sgml

Copy file name to clipboardExpand all lines: doc/src/sgml/func.sgml
+3-3Lines changed: 3 additions & 3 deletions
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

Copy file name to clipboardExpand all lines: src/backend/optimizer/prep/prepagg.c
+24-4Lines changed: 24 additions & 4 deletions
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

Copy file name to clipboardExpand all lines: src/backend/parser/parse_agg.c
+36-1Lines changed: 36 additions & 1 deletion
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.