aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeAgg.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-04-12 11:58:53 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-04-12 12:03:30 -0400
commita9d9acbf219b9e96585779cd5f99d674d4ccba74 (patch)
tree4bd26a78fa7f6f0bc558c611278e42a9f41d4875 /src/backend/executor/nodeAgg.c
parent3c41b812c5578fd7bd5c2de42941012d7d56dde2 (diff)
downloadpostgresql-a9d9acbf219b9e96585779cd5f99d674d4ccba74.tar.gz
postgresql-a9d9acbf219b9e96585779cd5f99d674d4ccba74.zip
Create infrastructure for moving-aggregate optimization.
Until now, when executing an aggregate function as a window function within a window with moving frame start (that is, any frame start mode except UNBOUNDED PRECEDING), we had to recalculate the aggregate from scratch each time the frame head moved. This patch allows an aggregate definition to include an alternate "moving aggregate" implementation that includes an inverse transition function for removing rows from the aggregate's running state. As long as this can be done successfully, runtime is proportional to the total number of input rows, rather than to the number of input rows times the average frame length. This commit includes the core infrastructure, documentation, and regression tests using user-defined aggregates. Follow-on commits will update some of the built-in aggregates to use this feature. David Rowley and Florian Pflug, reviewed by Dean Rasheed; additional hacking by me
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r--src/backend/executor/nodeAgg.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 7e4bca5b4d8..d60845bcd34 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1798,8 +1798,10 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggref->aggtype,
aggref->inputcollid,
transfn_oid,
+ InvalidOid, /* invtrans is not needed here */
finalfn_oid,
&transfnexpr,
+ NULL,
&finalfnexpr);
/* set up infrastructure for calling the transfn and finalfn */
@@ -1847,7 +1849,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
* type and transtype are the same (or at least binary-compatible), so
* that it's OK to use the first aggregated input value as the initial
* transValue. This should have been checked at agg definition time,
- * but just in case...
+ * but we must check again in case the transfn's strictness property
+ * has been changed.
*/
if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
{
@@ -2126,6 +2129,12 @@ ExecReScanAgg(AggState *node)
ExecReScan(node->ss.ps.lefttree);
}
+
+/***********************************************************************
+ * API exposed to aggregate functions
+ ***********************************************************************/
+
+
/*
* AggCheckCallContext - test if a SQL function is being called as an aggregate
*
@@ -2152,7 +2161,7 @@ AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
{
if (aggcontext)
- *aggcontext = ((WindowAggState *) fcinfo->context)->aggcontext;
+ *aggcontext = ((WindowAggState *) fcinfo->context)->curaggcontext;
return AGG_CONTEXT_WINDOW;
}