diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index ee1bcb84e28..18a5af6b919 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1364,6 +1364,96 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) } /* + * plan_is_disabled + * Checks if the given plan node type was disabled during query planning. + * This is evident by the disable_node field being higher than the sum of + * the disabled_node field from the plan's children. + */ +static bool +plan_is_disabled(Plan *plan) +{ + int child_disabled_nodes; + + /* The node is certainly not disabled if this is zero */ + if (plan->disabled_nodes == 0) + return false; + + child_disabled_nodes = 0; + + /* + * Handle special nodes first. Children of BitmapOrs and BitmapAnds can't + * be disabled, so no need to handle those specifically. + */ + if (IsA(plan, Append)) + { + ListCell *lc; + Append *aplan = (Append *) plan; + + /* + * Sum the Append childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, aplan->appendplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, MergeAppend)) + { + ListCell *lc; + MergeAppend *maplan = (MergeAppend *) plan; + + /* + * Sum the MergeAppend childrens' disabled_nodes. This purposefully + * includes any run-time pruned children. Ignoring those could give + * us the incorrect number of disabled nodes. + */ + foreach(lc, maplan->mergeplans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else if (IsA(plan, SubqueryScan)) + child_disabled_nodes += ((SubqueryScan *) plan)->subplan->disabled_nodes; + else if (IsA(plan, CustomScan)) + { + ListCell *lc; + CustomScan *cplan = (CustomScan *) plan; + + foreach(lc, cplan->custom_plans) + { + Plan *subplan = lfirst(lc); + + child_disabled_nodes += subplan->disabled_nodes; + } + } + else + { + /* + * Else, sum up disabled_nodes from the plan's inner and outer side. + */ + if (outerPlan(plan)) + child_disabled_nodes += outerPlan(plan)->disabled_nodes; + if (innerPlan(plan)) + child_disabled_nodes += innerPlan(plan)->disabled_nodes; + } + + /* + * It's disabled if the plan's disable_nodes is higher than the sum of its + * child's plan disabled_nodes. + */ + if (plan->disabled_nodes > child_disabled_nodes) + return true; + + return false; +} + +/* * ExplainNode - * Appends a description of a plan tree to es->str * @@ -1399,6 +1489,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainWorkersState *save_workers_state = es->workers_state; int save_indent = es->indent; bool haschildren; + bool isdisabled; /* * Prepare per-worker output buffers, if needed. We'll append the data in @@ -1914,9 +2005,10 @@ ExplainNode(PlanState *planstate, List *ancestors, if (es->format == EXPLAIN_FORMAT_TEXT) appendStringInfoChar(es->str, '\n'); - if (plan->disabled_nodes != 0) - ExplainPropertyInteger("Disabled Nodes", NULL, plan->disabled_nodes, - es); + + isdisabled = plan_is_disabled(plan); + if (es->format != EXPLAIN_FORMAT_TEXT || isdisabled) + ExplainPropertyBool("Disabled", isdisabled, es); /* prepare per-worker general execution details */ if (es->workers_state && es->verbose) |