aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeProjectSet.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeProjectSet.c')
-rw-r--r--src/backend/executor/nodeProjectSet.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 68981296f90..30789bcce4d 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -53,6 +53,13 @@ ExecProjectSet(PlanState *pstate)
econtext = node->ps.ps_ExprContext;
/*
+ * Reset per-tuple context to free expression-evaluation storage allocated
+ * for a potentially previously returned tuple. Note that the SRF argument
+ * context has a different lifetime and is reset below.
+ */
+ ResetExprContext(econtext);
+
+ /*
* Check to see if we're still projecting out tuples from a previous scan
* tuple (because there is a function-returning-set in the projection
* expressions). If so, try to project another one.
@@ -66,11 +73,13 @@ ExecProjectSet(PlanState *pstate)
}
/*
- * Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't happen
- * until we're done projecting out tuples from a scan tuple.
+ * Reset argument context to free any expression evaluation storage
+ * allocated in the previous tuple cycle. Note this can't happen until
+ * we're done projecting out tuples from a scan tuple, as ValuePerCall
+ * functions are allowed to reference the arguments for each returned
+ * tuple.
*/
- ResetExprContext(econtext);
+ MemoryContextReset(node->argcontext);
/*
* Get another input tuple and project SRFs from it.
@@ -164,7 +173,8 @@ ExecProjectSRF(ProjectSetState *node, bool continuing)
* Evaluate SRF - possibly continuing previously started output.
*/
*result = ExecMakeFunctionResultSet((SetExprState *) elem,
- econtext, isnull, isdone);
+ econtext, node->argcontext,
+ isnull, isdone);
if (*isdone != ExprEndResult)
hasresult = true;
@@ -291,6 +301,18 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
off++;
}
+
+ /*
+ * Create a memory context that ExecMakeFunctionResult 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 use one context for
+ * the arguments of all tSRFs, as they have roughly equivalent lifetimes.
+ */
+ state->argcontext = AllocSetContextCreate(CurrentMemoryContext,
+ "tSRF function arguments",
+ ALLOCSET_DEFAULT_SIZES);
+
return state;
}