Commit 38423232 authored by Tom Lane's avatar Tom Lane

Ensure set-returning functions in the targetlist of a plan node will be

shut down cleanly if the plan node is ReScanned before the SRFs are run
to completion.  This fixes the problem for SQL-language functions, but
still need work on functions using the SRF_XXX() macros.
parent 125d69cd
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.76 2003/11/29 19:51:48 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.77 2003/12/18 20:21:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -39,13 +39,20 @@ ...@@ -39,13 +39,20 @@
#include "executor/nodeUnique.h" #include "executor/nodeUnique.h"
/* ---------------------------------------------------------------- /*
* ExecReScan * ExecReScan
* Reset a plan node so that its output can be re-scanned.
*
* Note that if the plan node has parameters that have changed value,
* the output might be different from last time.
* *
* takes the new expression context as an argument, so that * The second parameter is currently only used to pass a NestLoop plan's
* index scans needn't have their scan keys updated separately * econtext down to its inner child plan, in case that is an indexscan that
* - marcel 09/20/94 * needs access to variables of the current outer tuple. (The handling of
* ---------------------------------------------------------------- * this parameter is currently pretty inconsistent: some callers pass NULL
* and some pass down their parent's value; so don't rely on it in other
* situations. It'd probably be better to remove the whole thing and use
* the generalized parameter mechanism instead.)
*/ */
void void
ExecReScan(PlanState *node, ExprContext *exprCtxt) ExecReScan(PlanState *node, ExprContext *exprCtxt)
...@@ -85,6 +92,11 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) ...@@ -85,6 +92,11 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
UpdateChangedParamSet(node->righttree, node->chgParam); UpdateChangedParamSet(node->righttree, node->chgParam);
} }
/* Shut down any SRFs in the plan node's targetlist */
if (node->ps_ExprContext)
ReScanExprContext(node->ps_ExprContext);
/* And do node-type-specific processing */
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_ResultState: case T_ResultState:
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.107 2003/11/29 19:51:48 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.108 2003/12/18 20:21:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* FreeExecutorState * FreeExecutorState
* CreateExprContext * CreateExprContext
* FreeExprContext * FreeExprContext
* ReScanExprContext
* *
* ExecAssignExprContext Common code for plan node init routines. * ExecAssignExprContext Common code for plan node init routines.
* ExecAssignResultType * ExecAssignResultType
...@@ -352,6 +353,24 @@ FreeExprContext(ExprContext *econtext) ...@@ -352,6 +353,24 @@ FreeExprContext(ExprContext *econtext)
pfree(econtext); pfree(econtext);
} }
/*
* ReScanExprContext
*
* Reset an expression context in preparation for a rescan of its
* plan node. This requires calling any registered shutdown callbacks,
* since any partially complete set-returning-functions must be canceled.
*
* Note we make no assumption about the caller's memory context.
*/
void
ReScanExprContext(ExprContext *econtext)
{
/* Call any registered callbacks */
ShutdownExprContext(econtext);
/* And clean up the memory used */
MemoryContextReset(econtext->ecxt_per_tuple_memory);
}
/* /*
* Build a per-output-tuple ExprContext for an EState. * Build a per-output-tuple ExprContext for an EState.
* *
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.103 2003/11/29 22:41:01 pgsql Exp $ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.104 2003/12/18 20:21:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -201,6 +201,7 @@ extern EState *CreateExecutorState(void); ...@@ -201,6 +201,7 @@ extern EState *CreateExecutorState(void);
extern void FreeExecutorState(EState *estate); extern void FreeExecutorState(EState *estate);
extern ExprContext *CreateExprContext(EState *estate); extern ExprContext *CreateExprContext(EState *estate);
extern void FreeExprContext(ExprContext *econtext); extern void FreeExprContext(ExprContext *econtext);
extern void ReScanExprContext(ExprContext *econtext);
#define ResetExprContext(econtext) \ #define ResetExprContext(econtext) \
MemoryContextReset((econtext)->ecxt_per_tuple_memory) MemoryContextReset((econtext)->ecxt_per_tuple_memory)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment