From c1f8fb9bfb0d2a89f646b3186a004d6e4ebdecb4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 19 Jun 2014 22:13:47 -0400 Subject: Avoid leaking memory while evaluating arguments for a table function. ExecMakeTableFunctionResult evaluated the arguments for a function-in-FROM in the query-lifespan memory context. This is insignificant in simple cases where the function relation is scanned only once; but if the function is in a sub-SELECT or is on the inside of a nested loop, any memory consumed during argument evaluation can add up quickly. (The potential for trouble here had been foreseen long ago, per existing comments; but we'd not previously seen a complaint from the field about it.) To fix, create an additional temporary context just for this purpose. Per an example from MauMau. Back-patch to all active branches. --- src/backend/executor/nodeFunctionscan.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/backend/executor/nodeFunctionscan.c') diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index e09c16177c3..283f547b426 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -25,6 +25,7 @@ #include "executor/nodeFunctionscan.h" #include "funcapi.h" #include "nodes/nodeFuncs.h" +#include "utils/memutils.h" static TupleTableSlot *FunctionNext(FunctionScanState *node); @@ -64,6 +65,7 @@ FunctionNext(FunctionScanState *node) node->tuplestorestate = tuplestorestate = ExecMakeTableFunctionResult(node->funcexpr, node->ss.ps.ps_ExprContext, + node->argcontext, node->tupdesc, node->eflags & EXEC_FLAG_BACKWARD); } @@ -227,6 +229,19 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); + /* + * Create a memory context that ExecMakeTableFunctionResult can use to + * evaluate function arguments in. We can't use the per-tuple context for + * this because it gets reset too often; but we don't want to leak + * evaluation results into the query-lifespan context either. We just + * need one context, because we evaluate each function separately. + */ + scanstate->argcontext = AllocSetContextCreate(CurrentMemoryContext, + "Table function arguments", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + return scanstate; } -- cgit v1.2.3