summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/tlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/tlist.c')
-rw-r--r--src/backend/optimizer/util/tlist.c45
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);
+ }
+ }
+}