diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 155 |
1 files changed, 147 insertions, 8 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 1e8f618a347..33252a8e205 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -51,6 +51,10 @@ static void ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es, 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 void ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es); @@ -539,9 +543,13 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc) { + Bitmapset *rels_used = NULL; + Assert(queryDesc->plannedstmt != NULL); es->pstmt = queryDesc->plannedstmt; es->rtable = queryDesc->plannedstmt->rtable; + ExplainPreScanNode(queryDesc->planstate, &rels_used); + es->rtable_names = select_rtable_names_for_explain(es->rtable, rels_used); ExplainNode(queryDesc->planstate, NIL, NULL, NULL, es); } @@ -641,6 +649,132 @@ elapsed_time(instr_time *starttime) } /* + * ExplainPreScanNode - + * Prescan the planstate tree to identify which RTEs are referenced + * + * Adds the relid of each referenced RTE to *rels_used. The result controls + * which RTEs are assigned aliases by select_rtable_names_for_explain. 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 +ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) +{ + Plan *plan = planstate->plan; + + switch (nodeTag(plan)) + { + case T_SeqScan: + case T_IndexScan: + case T_IndexOnlyScan: + case T_BitmapHeapScan: + case T_TidScan: + case T_SubqueryScan: + case T_FunctionScan: + case T_ValuesScan: + case T_CteScan: + case T_WorkTableScan: + case T_ForeignScan: + *rels_used = bms_add_member(*rels_used, + ((Scan *) plan)->scanrelid); + break; + case T_ModifyTable: + /* cf ExplainModifyTarget */ + *rels_used = bms_add_member(*rels_used, + linitial_int(((ModifyTable *) plan)->resultRelations)); + break; + default: + 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); + } +} + +/* * ExplainNode - * Appends a description of a plan tree to es->str * @@ -1440,7 +1574,8 @@ show_plan_tlist(PlanState *planstate, List *ancestors, ExplainState *es) /* Set up deparsing context */ context = deparse_context_for_planstate((Node *) planstate, ancestors, - es->rtable); + es->rtable, + es->rtable_names); useprefix = list_length(es->rtable) > 1; /* Deparse each result column (we now include resjunk ones) */ @@ -1471,7 +1606,8 @@ show_expression(Node *node, const char *qlabel, /* Set up deparsing context */ context = deparse_context_for_planstate((Node *) planstate, ancestors, - es->rtable); + es->rtable, + es->rtable_names); /* Deparse the expression */ exprstr = deparse_expression(node, context, useprefix, false); @@ -1573,7 +1709,8 @@ show_sort_keys_common(PlanState *planstate, int nkeys, AttrNumber *keycols, /* Set up deparsing context */ context = deparse_context_for_planstate((Node *) planstate, ancestors, - es->rtable); + es->rtable, + es->rtable_names); useprefix = (list_length(es->rtable) > 1 || es->verbose); for (keyno = 0; keyno < nkeys; keyno++) @@ -1813,8 +1950,10 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es) char *namespace = NULL; const char *objecttag = NULL; RangeTblEntry *rte; + char *refname; rte = rt_fetch(rti, es->rtable); + refname = (char *) list_nth(es->rtable_names, rti - 1); switch (nodeTag(plan)) { @@ -1887,10 +2026,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es) quote_identifier(objectname)); else if (objectname != NULL) appendStringInfo(es->str, " %s", quote_identifier(objectname)); - if (objectname == NULL || - strcmp(rte->eref->aliasname, objectname) != 0) - appendStringInfo(es->str, " %s", - quote_identifier(rte->eref->aliasname)); + if (refname != NULL && + (objectname == NULL || strcmp(refname, objectname) != 0)) + appendStringInfo(es->str, " %s", quote_identifier(refname)); } else { @@ -1898,7 +2036,8 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es) ExplainPropertyText(objecttag, objectname, es); if (namespace != NULL) ExplainPropertyText("Schema", namespace, es); - ExplainPropertyText("Alias", rte->eref->aliasname, es); + if (refname != NULL) + ExplainPropertyText("Alias", refname, es); } } |