diff options
Diffstat (limited to 'src/backend/nodes/nodeFuncs.c')
-rw-r--r-- | src/backend/nodes/nodeFuncs.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index c517dfd9d69..4a2447409a9 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -18,6 +18,7 @@ #include "catalog/pg_type.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "nodes/execnodes.h" #include "nodes/nodeFuncs.h" #include "nodes/relation.h" #include "utils/builtins.h" @@ -26,6 +27,10 @@ static bool expression_returns_set_walker(Node *node, void *context); static int leftmostLoc(int loc1, int loc2); +static bool planstate_walk_subplans(List *plans, bool (*walker) (), + void *context); +static bool planstate_walk_members(List *plans, PlanState **planstates, + bool (*walker) (), void *context); /* @@ -3412,3 +3417,123 @@ raw_expression_tree_walker(Node *node, } return false; } + +/* + * planstate_tree_walker --- walk plan state trees + * + * The walker has already visited the current node, and so we need only + * recurse into any sub-nodes it has. + */ +bool +planstate_tree_walker(PlanState *planstate, bool (*walker) (), void *context) +{ + Plan *plan = planstate->plan; + + /* initPlan-s */ + if (planstate_walk_subplans(planstate->initPlan, walker, context)) + return true; + + /* lefttree */ + if (outerPlanState(planstate)) + { + if (walker(outerPlanState(planstate), context)) + return true; + } + + /* righttree */ + if (innerPlanState(planstate)) + { + if (walker(innerPlanState(planstate), context)) + return true; + } + + /* special child plans */ + switch (nodeTag(plan)) + { + case T_ModifyTable: + if (planstate_walk_members(((ModifyTable *) plan)->plans, + ((ModifyTableState *) planstate)->mt_plans, + walker, context)) + return true; + break; + case T_Append: + if (planstate_walk_members(((Append *) plan)->appendplans, + ((AppendState *) planstate)->appendplans, + walker, context)) + return true; + break; + case T_MergeAppend: + if (planstate_walk_members(((MergeAppend *) plan)->mergeplans, + ((MergeAppendState *) planstate)->mergeplans, + walker, context)) + return true; + break; + case T_BitmapAnd: + if (planstate_walk_members(((BitmapAnd *) plan)->bitmapplans, + ((BitmapAndState *) planstate)->bitmapplans, + walker, context)) + return true; + break; + case T_BitmapOr: + if (planstate_walk_members(((BitmapOr *) plan)->bitmapplans, + ((BitmapOrState *) planstate)->bitmapplans, + walker, context)) + return true; + break; + case T_SubqueryScan: + if (walker(((SubqueryScanState *) planstate)->subplan, context)) + return true; + break; + default: + break; + } + + /* subPlan-s */ + if (planstate_walk_subplans(planstate->subPlan, walker, context)) + return true; + + return false; +} + +/* + * Walk a list of SubPlans (or initPlans, which also use SubPlan nodes). + */ +static bool +planstate_walk_subplans(List *plans, bool (*walker) (), void *context) +{ + ListCell *lc; + + foreach(lc, plans) + { + SubPlanState *sps = (SubPlanState *) lfirst(lc); + + Assert(IsA(sps, SubPlanState)); + if (walker(sps->planstate, context)) + return true; + } + + return false; +} + +/* + * Walk the constituent plans of a ModifyTable, Append, MergeAppend, + * BitmapAnd, or BitmapOr node. + * + * Note: we don't actually need to examine the Plan list members, but + * we need the list in order to determine the length of the PlanState array. + */ +static bool +planstate_walk_members(List *plans, PlanState **planstates, + bool (*walker) (), void *context) +{ + int nplans = list_length(plans); + int j; + + for (j = 0; j < nplans; j++) + { + if (walker(planstates[j], context)) + return true; + } + + return false; +} |