]> granicus.if.org Git - postgresql/blobdiff - src/backend/executor/nodeAgg.c
Create an official API function for C functions to use to check if they are
[postgresql] / src / backend / executor / nodeAgg.c
index fbdbebfa1665cf7b6e1fb2b007fe6c74437656d6..ea722f1ee3b0ee2924bc5c930d5ea196b27a7514 100644 (file)
  *       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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -1969,6 +1973,42 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
                ExecReScan(((PlanState *) node)->lefttree, 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
  *