aboutsummaryrefslogtreecommitdiff
path: root/src/backend/nodes/nodeFuncs.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2015-09-17 11:24:49 -0400
committerRobert Haas <rhaas@postgresql.org>2015-09-17 11:27:06 -0400
commit8dd401aa07b91d46f81e51321523864d32843523 (patch)
tree6f4074de97647b077785649c11775a79101eb5b4 /src/backend/nodes/nodeFuncs.c
parent293fd7c77e40cdf06b7a9eb6db95379be8869b04 (diff)
downloadpostgresql-8dd401aa07b91d46f81e51321523864d32843523.tar.gz
postgresql-8dd401aa07b91d46f81e51321523864d32843523.zip
Add new function planstate_tree_walker.
ExplainPreScanNode knows how to iterate over a generic tree of plan states; factor that logic out into a separate walker function so that other code, such as upcoming patches for parallel query, can also use it. Patch by me, reviewed by Tom Lane.
Diffstat (limited to 'src/backend/nodes/nodeFuncs.c')
-rw-r--r--src/backend/nodes/nodeFuncs.c125
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;
+}