static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
static void ExplainNode(PlanState *planstate, List *ancestors,
const char *relationship, const char *plan_name,
- ExplainState *es);
+ ExplainState *es, PlanState *squashstate);
static void show_plan_tlist(PlanState *planstate, List *ancestors,
ExplainState *es);
static void show_expression(Node *node, const char *qlabel,
es->rtable_names = select_rtable_names_for_explain(es->rtable, rels_used);
es->deparse_cxt = deparse_context_for_plan_rtable(es->rtable,
es->rtable_names);
- ExplainNode(queryDesc->planstate, NIL, NULL, NULL, es);
+ ExplainNode(queryDesc->planstate, NIL, NULL, NULL, es, NULL);
}
/*
static void
ExplainNode(PlanState *planstate, List *ancestors,
const char *relationship, const char *plan_name,
- ExplainState *es)
+ ExplainState *es, PlanState *squashstate)
{
Plan *plan = planstate->plan;
const char *pname; /* node type name for text output */
if (gather->single_copy)
{
ExplainNode(outerPlanState(planstate), ancestors, relationship,
- plan_name, es);
+ plan_name, es, planstate);
return;
}
}
/* initPlan-s */
if (planstate->initPlan)
ExplainSubPlans(planstate->initPlan, ancestors, "InitPlan", es);
+ if (squashstate != NULL && squashstate->initPlan)
+ ExplainSubPlans(squashstate->initPlan, ancestors, "SQUASHInitPlan", es);
/* lefttree */
if (outerPlanState(planstate))
ExplainNode(outerPlanState(planstate), ancestors,
- "Outer", NULL, es);
+ "Outer", NULL, es, NULL);
/* righttree */
if (innerPlanState(planstate))
ExplainNode(innerPlanState(planstate), ancestors,
- "Inner", NULL, es);
+ "Inner", NULL, es, NULL);
/* special child plans */
switch (nodeTag(plan))
break;
case T_SubqueryScan:
ExplainNode(((SubqueryScanState *) planstate)->subplan, ancestors,
- "Subquery", NULL, es);
+ "Subquery", NULL, es, NULL);
break;
case T_CustomScan:
ExplainCustomChildren((CustomScanState *) planstate,
/* subPlan-s */
if (planstate->subPlan)
ExplainSubPlans(planstate->subPlan, ancestors, "SubPlan", es);
+ if (squashstate != NULL && squashstate->subPlan)
+ {
+ List *myancestors = lcons(squashstate, ancestors);
+ ExplainSubPlans(squashstate->subPlan, myancestors, "SQUASHSubPlan", es);
+ }
/* end of child plans */
if (haschildren)
for (j = 0; j < nplans; j++)
ExplainNode(planstates[j], ancestors,
- "Member", NULL, es);
+ "Member", NULL, es, NULL);
}
/*
SubPlan *sp = (SubPlan *) sps->xprstate.expr;
ExplainNode(sps->planstate, ancestors,
- relationship, sp->plan_name, es);
+ relationship, sp->plan_name, es, NULL);
}
}
(list_length(css->custom_ps) != 1 ? "children" : "child");
foreach(cell, css->custom_ps)
- ExplainNode((PlanState *) lfirst(cell), ancestors, label, NULL, es);
+ ExplainNode((PlanState *) lfirst(cell), ancestors, label, NULL, es,
+ NULL);
}
/*
* results.
*/
bool need_sort_for_grouping = false;
+ Plan *checkplan;
+ bool insert_gather = false;
/* Try to run it in a worker. */
if (best_path->parallel_safe)
+ {
+ insert_gather = true;
best_path = (Path *)
create_single_copy_gather_path(root, final_rel,
best_path, NULL);
+ }
current_pathkeys = best_path->pathkeys;
result_plan = create_plan(root, best_path);
+ checkplan = result_plan;
+ if (insert_gather)
+ {
+ Assert(IsA(checkplan, Gather));
+ checkplan = outerPlan(checkplan);
+ Assert(!IsA(checkplan, Gather));
+ }
+
/*
* create_plan returns a plan with just a "flat" tlist of required
* Vars. Usually we need to insert the sub_tlist as the tlist of
* we need, we must insert a Result node to project the
* desired tlist.
*/
- if (!is_projection_capable_plan(result_plan) &&
+ if (!is_projection_capable_plan(checkplan) &&
!tlist_same_exprs(sub_tlist, result_plan->targetlist))
{
result_plan = (Plan *) make_result(root,