* ExplainPrintPlan - * convert a QueryDesc's plan tree to text and append it to es->str * * The caller should have set up the options fields of *es, as well as * initializing the output buffer es->str. Also, output formatting state * such as the indent level is assumed valid. Plan-tree-specific fields * in *es are initialized here. * * NB: will not work on utility statements */
| 987 | * NB: will not work on utility statements |
| 988 | */ |
| 989 | void |
| 990 | ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc) |
| 991 | { |
| 992 | EState *estate = queryDesc->estate; |
| 993 | Bitmapset *rels_used = NULL; |
| 994 | PlanState *ps; |
| 995 | |
| 996 | /* Set up ExplainState fields associated with this plan tree */ |
| 997 | Assert(queryDesc->plannedstmt != NULL); |
| 998 | es->pstmt = queryDesc->plannedstmt; |
| 999 | es->rtable = queryDesc->plannedstmt->rtable; |
| 1000 | es->showstatctx = queryDesc->showstatctx; |
| 1001 | |
| 1002 | /* CDB: Find slice table entry for the root slice. */ |
| 1003 | es->currentSlice = getCurrentSlice(estate, LocallyExecutingSliceIndex(estate)); |
| 1004 | |
| 1005 | /* |
| 1006 | * Get local stats if root slice was executed here in the qDisp, as long |
| 1007 | * as we haven't already gathered the statistics. This can happen when an |
| 1008 | * executor hook generates EXPLAIN output. |
| 1009 | */ |
| 1010 | if (es->analyze && !es->showstatctx->stats_gathered) |
| 1011 | { |
| 1012 | if (Gp_role != GP_ROLE_EXECUTE && (!es->currentSlice || sliceRunsOnQD(es->currentSlice))) |
| 1013 | cdbexplain_localExecStats(queryDesc->planstate, es->showstatctx); |
| 1014 | |
| 1015 | /* Fill in the plan's Instrumentation with stats from qExecs. */ |
| 1016 | if (estate->dispatcherState && estate->dispatcherState->primaryResults) |
| 1017 | cdbexplain_recvExecStats(queryDesc->planstate, |
| 1018 | estate->dispatcherState->primaryResults, |
| 1019 | LocallyExecutingSliceIndex(estate), |
| 1020 | es->showstatctx); |
| 1021 | } |
| 1022 | |
| 1023 | ExplainPreScanNode(queryDesc->planstate, &rels_used); |
| 1024 | es->rtable_names = select_rtable_names_for_explain(es->rtable, rels_used); |
| 1025 | es->deparse_cxt = deparse_context_for_plan_tree(queryDesc->plannedstmt, |
| 1026 | es->rtable_names); |
| 1027 | es->printed_subplans = NULL; |
| 1028 | |
| 1029 | /* |
| 1030 | * Sometimes we mark a Gather node as "invisible", which means that it's |
| 1031 | * not to be displayed in EXPLAIN output. The purpose of this is to allow |
| 1032 | * running regression tests with force_parallel_mode=regress to get the |
| 1033 | * same results as running the same tests with force_parallel_mode=off. |
| 1034 | * Such marking is currently only supported on a Gather at the top of the |
| 1035 | * plan. We skip that node, and we must also hide per-worker detail data |
| 1036 | * further down in the plan tree. |
| 1037 | */ |
| 1038 | ps = queryDesc->planstate; |
| 1039 | if (IsA(ps, GatherState) && ((Gather *) ps->plan)->invisible) |
| 1040 | { |
| 1041 | ps = outerPlanState(ps); |
| 1042 | es->hide_workers = true; |
| 1043 | } |
| 1044 | ExplainNode(ps, NIL, NULL, NULL, es); |
| 1045 | |
| 1046 | /* |
no test coverage detected