diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 9befca9016..fcb8b56999 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -370,12 +370,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags) break; } - /* - * Add a wrapper around the ExecProcNode callback that checks stack depth - * during the first execution. - */ - result->ExecProcNodeReal = result->ExecProcNode; - result->ExecProcNode = ExecProcNodeFirst; + ExecSetExecProcNode(result, result->ExecProcNode); /* * Initialize any initPlans present in this node. The planner put them in @@ -401,6 +396,27 @@ ExecInitNode(Plan *node, EState *estate, int eflags) } +/* + * If a node wants to change its ExecProcNode function after ExecInitNode() + * has finished, it should do so with this function. That way any wrapper + * functions can be reinstalled, without the node having to know how that + * works. + */ +void +ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function) +{ + /* + * Add a wrapper around the ExecProcNode callback that checks stack depth + * during the first execution and maybe adds an instrumentation + * wrapper. When the callback is changed after execution has already begun + * that means we'll superflously execute ExecProcNodeFirst, but that seems + * ok. + */ + node->ExecProcNodeReal = function; + node->ExecProcNode = ExecProcNodeFirst; +} + + /* * ExecProcNode wrapper that performs some one-time checks, before calling * the relevant node method (possibly via an instrumentation wrapper). diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index b5578f5855..dea9216fd6 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -219,6 +219,7 @@ extern void EvalPlanQualEnd(EPQState *epqstate); * functions in execProcnode.c */ extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags); +extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function); extern Node *MultiExecProcNode(PlanState *node); extern void ExecEndNode(PlanState *node); extern bool ExecShutdownNode(PlanState *node);