aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeAgg.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-02-08 20:39:52 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-02-08 20:39:52 +0000
commitd5768dce10576c2fb1254c03fb29475d4fac6bb4 (patch)
tree7b971cb06b6671d66df26027909e1d9355d65d14 /src/backend/executor/nodeAgg.c
parent4d3d2e2b0325e3d6d524c6801b7439d3aaea4520 (diff)
downloadpostgresql-d5768dce10576c2fb1254c03fb29475d4fac6bb4.tar.gz
postgresql-d5768dce10576c2fb1254c03fb29475d4fac6bb4.zip
Create an official API function for C functions to use to check if they are
being called as aggregates, and to get the aggregate transition state memory context if needed. Use it instead of poking directly into AggState and WindowAggState in places that shouldn't know so much. We should have done this in 8.4, probably, but better late than never. Revised version of a patch by Hitoshi Harada.
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r--src/backend/executor/nodeAgg.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index fbdbebfa166..ea722f1ee3b 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -44,30 +44,34 @@
* is used to run finalize functions and compute the output tuple;
* this context can be reset once per output tuple.
*
- * Beginning in PostgreSQL 8.1, the executor's AggState node is passed as
- * the fmgr "context" value in all transfunc and finalfunc calls. It is
- * not really intended that the transition functions will look into the
- * AggState node, but they can use code like
- * if (fcinfo->context && IsA(fcinfo->context, AggState))
- * to verify that they are being called by nodeAgg.c and not as ordinary
- * SQL functions. The main reason a transition function might want to know
- * that is that it can avoid palloc'ing a fixed-size pass-by-ref transition
- * value on every call: it can instead just scribble on and return its left
- * input. Ordinarily it is completely forbidden for functions to modify
- * pass-by-ref inputs, but in the aggregate case we know the left input is
- * either the initial transition value or a previous function result, and
- * in either case its value need not be preserved. See int8inc() for an
- * example. Notice that advance_transition_function() is coded to avoid a
- * data copy step when the previous transition value pointer is returned.
- * Also, some transition functions make use of the aggcontext to store
- * working state.
+ * The executor's AggState node is passed as the fmgr "context" value in
+ * all transfunc and finalfunc calls. It is not recommended that the
+ * transition functions look at the AggState node directly, but they can
+ * use AggCheckCallContext() to verify that they are being called by
+ * nodeAgg.c (and not as ordinary SQL functions). The main reason a
+ * transition function might want to know this is so that it can avoid
+ * palloc'ing a fixed-size pass-by-ref transition value on every call:
+ * it can instead just scribble on and return its left input. Ordinarily
+ * it is completely forbidden for functions to modify pass-by-ref inputs,
+ * but in the aggregate case we know the left input is either the initial
+ * transition value or a previous function result, and in either case its
+ * value need not be preserved. See int8inc() for an example. Notice that
+ * advance_transition_function() is coded to avoid a data copy step when
+ * the previous transition value pointer is returned. Also, some
+ * transition functions want to store working state in addition to the
+ * nominal transition value; they can use the memory context returned by
+ * AggCheckCallContext() to do that.
+ *
+ * Note: AggCheckCallContext() is available as of PostgreSQL 9.0. The
+ * AggState is available as context in earlier releases (back to 8.1),
+ * but direct examination of the node is needed to use it before 9.0.
*
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.171 2010/01/02 16:57:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.172 2010/02/08 20:39:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1970,6 +1974,42 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
}
/*
+ * AggCheckCallContext - test if a SQL function is being called as an aggregate
+ *
+ * The transition and/or final functions of an aggregate may want to verify
+ * that they are being called as aggregates, rather than as plain SQL
+ * functions. They should use this function to do so. The return value
+ * is nonzero if being called as an aggregate, or zero if not. (Specific
+ * nonzero values are AGG_CONTEXT_AGGREGATE or AGG_CONTEXT_WINDOW, but more
+ * values could conceivably appear in future.)
+ *
+ * If aggcontext isn't NULL, the function also stores at *aggcontext the
+ * identity of the memory context that aggregate transition values are
+ * being stored in.
+ */
+int
+AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
+{
+ if (fcinfo->context && IsA(fcinfo->context, AggState))
+ {
+ if (aggcontext)
+ *aggcontext = ((AggState *) fcinfo->context)->aggcontext;
+ return AGG_CONTEXT_AGGREGATE;
+ }
+ if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
+ {
+ if (aggcontext)
+ *aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
+ return AGG_CONTEXT_WINDOW;
+ }
+
+ /* this is just to prevent "uninitialized variable" warnings */
+ if (aggcontext)
+ *aggcontext = NULL;
+ return 0;
+}
+
+/*
* aggregate_dummy - dummy execution routine for aggregate functions
*
* This function is listed as the implementation (prosrc field) of pg_proc