From 0d748d9bcc9da728027f076da598924709acd475 Mon Sep 17 00:00:00 2001 From: Kuien Liu Date: Fri, 8 Apr 2016 13:19:32 +0800 Subject: [PATCH] Backport AggCheckCallContext() (#607) Backport below commit from upstream: commit d5768dce10576c2fb1254c03fb29475d4fac6bb4 Author: Tom Lane Date: Mon Feb 8 20:39:52 2010 +0000 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. modified: src/backend/executor/nodeAgg.c modified: src/include/fmgr.h --- src/backend/executor/nodeAgg.c | 43 ++++++++++++++++++++++++++++++++++ src/include/fmgr.h | 13 ++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 4083981494..7174c0609c 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -2576,6 +2576,49 @@ ExecAggExplainEnd(PlanState *planstate, struct StringInfoData *buf) (double)MemoryContextGetPeakSpace(aggstate->aggcontext); } /* ExecAggExplainEnd */ +/* + * 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; + } + +/* + * TODO: remove the macro after we upgrade GPDB to PG8.4 due to WindowAggState + * is not supported yet. + */ +#if PG_VERSION_NUM >= 80400 + if (fcinfo->context && IsA(fcinfo->context, WindowAggState)) + { + if (aggcontext) + *aggcontext = ((WindowAggState *) fcinfo->context)->wincontext; + return AGG_CONTEXT_WINDOW; + } +#endif + + /* this is just to prevent "uninitialized variable" warnings */ + if (aggcontext) + *aggcontext = NULL; + return 0; +} + /* * aggregate_dummy - dummy execution routine for aggregate functions * diff --git a/src/include/fmgr.h b/src/include/fmgr.h index df7c0696a3..1914cc8dca 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -570,5 +570,18 @@ extern PGFunction lookup_external_function(void *filehandle, char *funcname); extern void load_file(const char *filename, bool restricted); extern void **find_rendezvous_variable(const char *varName); +/* + * Support for aggregate functions + * + * This is actually in executor/nodeAgg.c, but we declare it here since the + * whole point is for callers of it to not be overly friendly with nodeAgg. + */ + +/* AggCheckCallContext can return one of the following codes, or 0: */ +#define AGG_CONTEXT_AGGREGATE 1 /* regular aggregate */ +#define AGG_CONTEXT_WINDOW 2 /* window function */ + +extern int AggCheckCallContext(FunctionCallInfo fcinfo, + MemoryContext *aggcontext); #endif /* FMGR_H */ -- GitLab