agg_memorycontext.20100123.patch
application/octet-stream
Filename: agg_memorycontext.20100123.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| contrib/tsearch2/tsearch2.c | 4 | 0 |
| src/backend/executor/nodeAgg.c | 27 | 0 |
| src/backend/executor/nodeWindowAgg.c | 22 | 0 |
| src/backend/utils/adt/array_userfuncs.c | 4 | 0 |
| src/include/executor/nodeAgg.h | 1 | 0 |
| src/include/nodes/execnodes.h | 2 | 0 |
*** a/contrib/tsearch2/tsearch2.c
--- b/contrib/tsearch2/tsearch2.c
***************
*** 16,21 ****
--- 16,22 ----
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
+ #include "executor/nodeAgg.h"
#include "fmgr.h"
#include "tsearch/ts_utils.h"
#include "utils/builtins.h"
***************
*** 421,435 **** tsa_rewrite_accum(PG_FUNCTION_ARGS)
int nelemsp;
MemoryContext aggcontext;
MemoryContext oldcontext;
! if (fcinfo->context && IsA(fcinfo->context, AggState))
! aggcontext = ((AggState *) fcinfo->context)->aggcontext;
! else if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
! aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
! else
{
elog(ERROR, "tsa_rewrite_accum called in non-aggregate context");
- aggcontext = NULL; /* keep compiler quiet */
}
if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
--- 422,433 ----
int nelemsp;
MemoryContext aggcontext;
MemoryContext oldcontext;
+ bool iswindowagg;
! aggcontext = AggGetMemoryContext((Node *) fcinfo->context, &iswindowagg);
! if (!aggcontext)
{
elog(ERROR, "tsa_rewrite_accum called in non-aggregate context");
}
if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
*** a/src/backend/executor/nodeAgg.c
--- b/src/backend/executor/nodeAgg.c
***************
*** 1970,1975 **** ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
--- 1970,2002 ----
}
/*
+ * AggGetMemoryContext - an API to expose temporary memory space
+ *
+ * Eventually, aggregate functions want its own memory space to
+ * store user variables or states during executions of transition functions.
+ * For those functions to do it, we abstract the operation so that
+ * future internal changes don't affect them.
+ */
+ MemoryContext
+ AggGetMemoryContext(Node *node, bool *iswindowagg)
+ {
+ if (node && IsA(node, AggState))
+ {
+ if (iswindowagg)
+ *iswindowagg = false;
+ return ((AggState *) node)->aggcontext;
+ }
+ else if (node && IsA(node, WindowAggState))
+ {
+ if (iswindowagg)
+ *iswindowagg = true;
+ return ((WindowAggState *) node)->aggcontext;
+ }
+
+ return NULL;
+ }
+
+ /*
* aggregate_dummy - dummy execution routine for aggregate functions
*
* This function is listed as the implementation (prosrc field) of pg_proc
*** a/src/backend/executor/nodeWindowAgg.c
--- b/src/backend/executor/nodeWindowAgg.c
***************
*** 193,199 **** initialize_windowaggregate(WindowAggState *winstate,
peraggstate->transValue = peraggstate->initValue;
else
{
! oldContext = MemoryContextSwitchTo(winstate->wincontext);
peraggstate->transValue = datumCopy(peraggstate->initValue,
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
--- 193,199 ----
peraggstate->transValue = peraggstate->initValue;
else
{
! oldContext = MemoryContextSwitchTo(winstate->aggcontext);
peraggstate->transValue = datumCopy(peraggstate->initValue,
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
***************
*** 258,267 **** advance_windowaggregate(WindowAggState *winstate,
* already checked that the agg's input type is binary-compatible
* with its transtype, so straight copy here is OK.)
*
! * We must copy the datum into wincontext if it is pass-by-ref. We
* do not need to pfree the old transValue, since it's NULL.
*/
! MemoryContextSwitchTo(winstate->wincontext);
peraggstate->transValue = datumCopy(fcinfo->arg[1],
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
--- 258,267 ----
* already checked that the agg's input type is binary-compatible
* with its transtype, so straight copy here is OK.)
*
! * We must copy the datum into aggcontext if it is pass-by-ref. We
* do not need to pfree the old transValue, since it's NULL.
*/
! MemoryContextSwitchTo(winstate->aggcontext);
peraggstate->transValue = datumCopy(fcinfo->arg[1],
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
***************
*** 294,300 **** advance_windowaggregate(WindowAggState *winstate,
newVal = FunctionCallInvoke(fcinfo);
/*
! * If pass-by-ref datatype, must copy the new value into wincontext and
* pfree the prior transValue. But if transfn returned a pointer to its
* first input, we don't need to do anything.
*/
--- 294,300 ----
newVal = FunctionCallInvoke(fcinfo);
/*
! * If pass-by-ref datatype, must copy the new value into aggcontext and
* pfree the prior transValue. But if transfn returned a pointer to its
* first input, we don't need to do anything.
*/
***************
*** 303,309 **** advance_windowaggregate(WindowAggState *winstate,
{
if (!fcinfo->isnull)
{
! MemoryContextSwitchTo(winstate->wincontext);
newVal = datumCopy(newVal,
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
--- 303,309 ----
{
if (!fcinfo->isnull)
{
! MemoryContextSwitchTo(winstate->aggcontext);
newVal = datumCopy(newVal,
peraggstate->transtypeByVal,
peraggstate->transtypeLen);
***************
*** 544,554 **** eval_windowaggregates(WindowAggState *winstate)
pfree(DatumGetPointer(peraggstate->resultValue));
/*
! * If pass-by-ref, copy it into our global context.
*/
if (!*isnull)
{
! oldContext = MemoryContextSwitchTo(winstate->wincontext);
peraggstate->resultValue =
datumCopy(*result,
peraggstate->resulttypeByVal,
--- 544,554 ----
pfree(DatumGetPointer(peraggstate->resultValue));
/*
! * If pass-by-ref, copy it into our aggregate context.
*/
if (!*isnull)
{
! oldContext = MemoryContextSwitchTo(winstate->aggcontext);
peraggstate->resultValue =
datumCopy(*result,
peraggstate->resulttypeByVal,
***************
*** 789,795 **** release_partition(WindowAggState *winstate)
* any aggregate temp data). We don't rely on retail pfree because some
* aggregates might have allocated data we don't have direct pointers to.
*/
! MemoryContextResetAndDeleteChildren(winstate->wincontext);
if (winstate->buffer)
tuplestore_end(winstate->buffer);
--- 789,796 ----
* any aggregate temp data). We don't rely on retail pfree because some
* aggregates might have allocated data we don't have direct pointers to.
*/
! MemoryContextResetAndDeleteChildren(winstate->partition_context);
! MemoryContextResetAndDeleteChildren(winstate->aggcontext);
if (winstate->buffer)
tuplestore_end(winstate->buffer);
***************
*** 1099,1112 **** ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
winstate->tmpcontext = tmpcontext;
ExecAssignExprContext(estate, &winstate->ss.ps);
! /* Create long-lived context for storage of aggregate transvalues etc */
! winstate->wincontext =
AllocSetContextCreate(CurrentMemoryContext,
! "WindowAggContext",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/*
* tuple table initialization
*/
--- 1100,1120 ----
winstate->tmpcontext = tmpcontext;
ExecAssignExprContext(estate, &winstate->ss.ps);
! /* Create long-lived context for storage of partition-local memory etc */
! winstate->partition_context =
AllocSetContextCreate(CurrentMemoryContext,
! "WindowAggContextWin",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
+ /* Create mid-lived context for aggregate trans values etc */
+ winstate->aggcontext =
+ AllocSetContextCreate(CurrentMemoryContext,
+ "WindowAggContextAgg",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
/*
* tuple table initialization
*/
***************
*** 1297,1303 **** ExecEndWindowAgg(WindowAggState *node)
node->ss.ps.ps_ExprContext = node->tmpcontext;
ExecFreeExprContext(&node->ss.ps);
! MemoryContextDelete(node->wincontext);
outerPlan = outerPlanState(node);
ExecEndNode(outerPlan);
--- 1305,1312 ----
node->ss.ps.ps_ExprContext = node->tmpcontext;
ExecFreeExprContext(&node->ss.ps);
! MemoryContextDelete(node->partition_context);
! MemoryContextDelete(node->aggcontext);
outerPlan = outerPlanState(node);
ExecEndNode(outerPlan);
***************
*** 1616,1622 **** WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
{
Assert(WindowObjectIsValid(winobj));
if (winobj->localmem == NULL)
! winobj->localmem = MemoryContextAllocZero(winobj->winstate->wincontext,
sz);
return winobj->localmem;
}
--- 1625,1631 ----
{
Assert(WindowObjectIsValid(winobj));
if (winobj->localmem == NULL)
! winobj->localmem = MemoryContextAllocZero(winobj->winstate->partition_context,
sz);
return winobj->localmem;
}
*** a/src/backend/utils/adt/array_userfuncs.c
--- b/src/backend/utils/adt/array_userfuncs.c
***************
*** 12,17 ****
--- 12,18 ----
*/
#include "postgres.h"
+ #include "executor/nodeAgg.h"
#include "nodes/execnodes.h"
#include "utils/array.h"
#include "utils/builtins.h"
***************
*** 476,481 **** array_agg_transfn(PG_FUNCTION_ARGS)
--- 477,483 ----
{
Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1);
MemoryContext aggcontext;
+ bool iswindowagg;
ArrayBuildState *state;
Datum elem;
***************
*** 484,498 **** array_agg_transfn(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data type")));
! if (fcinfo->context && IsA(fcinfo->context, AggState))
! aggcontext = ((AggState *) fcinfo->context)->aggcontext;
! else if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
! aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
! else
{
/* cannot be called directly because of internal-type argument */
elog(ERROR, "array_agg_transfn called in non-aggregate context");
- aggcontext = NULL; /* keep compiler quiet */
}
state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
--- 486,496 ----
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("could not determine input data type")));
! aggcontext = AggGetMemoryContext((Node *) fcinfo->context, &iswindowagg);
! if (!aggcontext)
{
/* cannot be called directly because of internal-type argument */
elog(ERROR, "array_agg_transfn called in non-aggregate context");
}
state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
*** a/src/include/executor/nodeAgg.h
--- b/src/include/executor/nodeAgg.h
***************
*** 23,28 **** extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt);
--- 23,29 ----
extern Size hash_agg_entry_size(int numAggs);
+ extern MemoryContext AggGetMemoryContext(Node *node, bool *iswindowagg);
extern Datum aggregate_dummy(PG_FUNCTION_ARGS);
#endif /* NODEAGG_H */
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
***************
*** 1601,1607 **** typedef struct WindowAggState
int64 frametailpos; /* current frame tail position */
int64 aggregatedupto; /* rows before this one are aggregated */
! MemoryContext wincontext; /* context for partition-lifespan data */
ExprContext *tmpcontext; /* short-term evaluation context */
bool all_done; /* true if the scan is finished */
--- 1601,1608 ----
int64 frametailpos; /* current frame tail position */
int64 aggregatedupto; /* rows before this one are aggregated */
! MemoryContext partition_context; /* context for partition-lifespan data */
! MemoryContext aggcontext; /* context for each aggregate data */
ExprContext *tmpcontext; /* short-term evaluation context */
bool all_done; /* true if the scan is finished */