1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Simplify planner's final setup of Aggrefs for partial aggregation.

Commit e06a38965's original coding for constructing the execution-time
expression tree for a combining aggregate was rather messy, involving
duplicating quite a lot of code in setrefs.c so that it could inject
a nonstandard matching rule for Aggrefs.  Get rid of that in favor of
explicitly constructing a combining Aggref with a partial Aggref as input,
then allowing setref's normal matching logic to match the partial Aggref
to the output of the lower plan node and hence replace it with a Var.

In passing, rename and redocument make_partialgroup_input_target to have
some connection to what it actually does.
This commit is contained in:
Tom Lane
2016-06-26 12:08:12 -04:00
parent e3ad3ffa68
commit 59a3795c25
5 changed files with 174 additions and 337 deletions

View File

@ -14,12 +14,9 @@
*/
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/tlist.h"
#include "utils/syscache.h"
/*****************************************************************************
@ -762,51 +759,3 @@ apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
i++;
}
}
/*
* apply_partialaggref_adjustment
* Convert PathTarget to be suitable for a partial aggregate node. We simply
* adjust any Aggref nodes found in the target and set the aggoutputtype
* appropriately. This allows exprType() to return the
* actual type that will be produced.
*
* Note: We expect 'target' to be a flat target list and not have Aggrefs buried
* within other expressions.
*/
void
apply_partialaggref_adjustment(PathTarget *target)
{
ListCell *lc;
foreach(lc, target->exprs)
{
Aggref *aggref = (Aggref *) lfirst(lc);
if (IsA(aggref, Aggref))
{
Aggref *newaggref;
newaggref = (Aggref *) copyObject(aggref);
/*
* Normally, a partial aggregate returns the aggregate's
* transition type, but if that's INTERNAL, it returns BYTEA
* instead. (XXX this assumes we're doing parallel aggregate with
* serialization; later we might need an argument to tell this
* function whether we're doing parallel or just local partial
* aggregation.)
*/
Assert(OidIsValid(newaggref->aggtranstype));
if (newaggref->aggtranstype == INTERNALOID)
newaggref->aggoutputtype = BYTEAOID;
else
newaggref->aggoutputtype = newaggref->aggtranstype;
/* flag it as partial */
newaggref->aggpartial = true;
lfirst(lc) = newaggref;
}
}
}