static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
ExplainState *es);
static double elapsed_time(instr_time *starttime);
-static void ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
-static void ExplainPreScanMemberNodes(List *plans, PlanState **planstates,
- Bitmapset **rels_used);
-static void ExplainPreScanSubPlans(List *plans, Bitmapset **rels_used);
+static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
static void ExplainNode(PlanState *planstate, List *ancestors,
const char *relationship, const char *plan_name,
ExplainState *es);
* This ensures that we don't confusingly assign un-suffixed aliases to RTEs
* that never appear in the EXPLAIN output (such as inheritance parents).
*/
-static void
+static bool
ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
{
Plan *plan = planstate->plan;
break;
}
- /* initPlan-s */
- if (planstate->initPlan)
- ExplainPreScanSubPlans(planstate->initPlan, rels_used);
-
- /* lefttree */
- if (outerPlanState(planstate))
- ExplainPreScanNode(outerPlanState(planstate), rels_used);
-
- /* righttree */
- if (innerPlanState(planstate))
- ExplainPreScanNode(innerPlanState(planstate), rels_used);
-
- /* special child plans */
- switch (nodeTag(plan))
- {
- case T_ModifyTable:
- ExplainPreScanMemberNodes(((ModifyTable *) plan)->plans,
- ((ModifyTableState *) planstate)->mt_plans,
- rels_used);
- break;
- case T_Append:
- ExplainPreScanMemberNodes(((Append *) plan)->appendplans,
- ((AppendState *) planstate)->appendplans,
- rels_used);
- break;
- case T_MergeAppend:
- ExplainPreScanMemberNodes(((MergeAppend *) plan)->mergeplans,
- ((MergeAppendState *) planstate)->mergeplans,
- rels_used);
- break;
- case T_BitmapAnd:
- ExplainPreScanMemberNodes(((BitmapAnd *) plan)->bitmapplans,
- ((BitmapAndState *) planstate)->bitmapplans,
- rels_used);
- break;
- case T_BitmapOr:
- ExplainPreScanMemberNodes(((BitmapOr *) plan)->bitmapplans,
- ((BitmapOrState *) planstate)->bitmapplans,
- rels_used);
- break;
- case T_SubqueryScan:
- ExplainPreScanNode(((SubqueryScanState *) planstate)->subplan,
- rels_used);
- break;
- default:
- break;
- }
-
- /* subPlan-s */
- if (planstate->subPlan)
- ExplainPreScanSubPlans(planstate->subPlan, rels_used);
-}
-
-/*
- * Prescan 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 void
-ExplainPreScanMemberNodes(List *plans, PlanState **planstates,
- Bitmapset **rels_used)
-{
- int nplans = list_length(plans);
- int j;
-
- for (j = 0; j < nplans; j++)
- ExplainPreScanNode(planstates[j], rels_used);
-}
-
-/*
- * Prescan a list of SubPlans (or initPlans, which also use SubPlan nodes).
- */
-static void
-ExplainPreScanSubPlans(List *plans, Bitmapset **rels_used)
-{
- ListCell *lst;
-
- foreach(lst, plans)
- {
- SubPlanState *sps = (SubPlanState *) lfirst(lst);
-
- ExplainPreScanNode(sps->planstate, rels_used);
- }
+ return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
}
/*
#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"
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);
/*
}
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;
+}
extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
void *context);
+struct PlanState;
+extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
+ void *context);
+
#endif /* NODEFUNCS_H */