diff options
Diffstat (limited to 'src/backend/optimizer/util/tlist.c')
| -rw-r--r-- | src/backend/optimizer/util/tlist.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index b297d87e7e..cd421b1463 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -14,9 +14,12 @@ */ #include "postgres.h" +#include "access/htup_details.h" +#include "catalog/pg_aggregate.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/tlist.h" +#include "utils/syscache.h" /***************************************************************************** @@ -748,3 +751,45 @@ 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 to + * the aggtranstype. 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 burried + * within other expressions. + */ +void +apply_partialaggref_adjustment(PathTarget *target) +{ + ListCell *lc; + + foreach(lc, target->exprs) + { + Aggref *aggref = (Aggref *) lfirst(lc); + + if (IsA(aggref, Aggref)) + { + HeapTuple aggTuple; + Form_pg_aggregate aggform; + Aggref *newaggref; + + aggTuple = SearchSysCache1(AGGFNOID, + ObjectIdGetDatum(aggref->aggfnoid)); + if (!HeapTupleIsValid(aggTuple)) + elog(ERROR, "cache lookup failed for aggregate %u", + aggref->aggfnoid); + aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); + + newaggref = (Aggref *) copyObject(aggref); + newaggref->aggoutputtype = aggform->aggtranstype; + + lfirst(lc) = newaggref; + + ReleaseSysCache(aggTuple); + } + } +} |
