Commit 538d114f authored by Andres Freund's avatar Andres Freund

Allow executor nodes to change their ExecProcNode function.

In order for executor nodes to be able to change their ExecProcNode function
after ExecInitNode() has finished, provide ExecSetExecProcNode().  This allows
any wrappers functions that only execProcnode.c knows about to be reinstalled.
The motivation for wanting to change ExecProcNode after ExecInitNode() has
finished is that it is not known until later whether parallel query is
available, so if a parallel variant is to be installed then ExecInitNode()
is too soon to decide.

Author: Thomas Munro
Reviewed-By: Andres Freund
Discussion: https://postgr.es/m/CAEepm=09rr65VN+cAV5FgyM_z=D77Xy8Fuc9CDDDYbq3pQUezg@mail.gmail.com
parent dbb3d6f0
...@@ -370,12 +370,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags) ...@@ -370,12 +370,7 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
break; break;
} }
/* ExecSetExecProcNode(result, result->ExecProcNode);
* Add a wrapper around the ExecProcNode callback that checks stack depth
* during the first execution.
*/
result->ExecProcNodeReal = result->ExecProcNode;
result->ExecProcNode = ExecProcNodeFirst;
/* /*
* Initialize any initPlans present in this node. The planner put them in * Initialize any initPlans present in this node. The planner put them in
...@@ -401,6 +396,27 @@ ExecInitNode(Plan *node, EState *estate, int eflags) ...@@ -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 * ExecProcNode wrapper that performs some one-time checks, before calling
* the relevant node method (possibly via an instrumentation wrapper). * the relevant node method (possibly via an instrumentation wrapper).
......
...@@ -219,6 +219,7 @@ extern void EvalPlanQualEnd(EPQState *epqstate); ...@@ -219,6 +219,7 @@ extern void EvalPlanQualEnd(EPQState *epqstate);
* functions in execProcnode.c * functions in execProcnode.c
*/ */
extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags); extern PlanState *ExecInitNode(Plan *node, EState *estate, int eflags);
extern void ExecSetExecProcNode(PlanState *node, ExecProcNodeMtd function);
extern Node *MultiExecProcNode(PlanState *node); extern Node *MultiExecProcNode(PlanState *node);
extern void ExecEndNode(PlanState *node); extern void ExecEndNode(PlanState *node);
extern bool ExecShutdownNode(PlanState *node); extern bool ExecShutdownNode(PlanState *node);
......
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