diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/explain.c | 117 |
1 files changed, 115 insertions, 2 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index adefc5471a3..19ffcc2cacb 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -107,6 +107,11 @@ static void show_sort_group_keys(PlanState *planstate, const char *qlabel, List *ancestors, ExplainState *es); static void show_sortorder_options(StringInfo buf, Node *sortexpr, Oid sortOperator, Oid collation, bool nullsFirst); +static void show_window_def(WindowAggState *planstate, + List *ancestors, ExplainState *es); +static void show_window_keys(StringInfo buf, PlanState *planstate, + int nkeys, AttrNumber *keycols, + List *ancestors, ExplainState *es); static void show_storage_info(char *maxStorageType, int64 maxSpaceUsed, ExplainState *es); static void show_tablesample(TableSampleClause *tsc, PlanState *planstate, @@ -2333,12 +2338,13 @@ ExplainNode(PlanState *planstate, List *ancestors, planstate, es); break; case T_WindowAgg: + show_window_def(castNode(WindowAggState, planstate), ancestors, es); + show_upper_qual(((WindowAgg *) plan)->runConditionOrig, + "Run Condition", planstate, ancestors, es); show_upper_qual(plan->qual, "Filter", planstate, ancestors, es); if (plan->qual) show_instrumentation_count("Rows Removed by Filter", 1, planstate, es); - show_upper_qual(((WindowAgg *) plan)->runConditionOrig, - "Run Condition", planstate, ancestors, es); show_windowagg_info(castNode(WindowAggState, planstate), es); break; case T_Group: @@ -3008,6 +3014,113 @@ show_sortorder_options(StringInfo buf, Node *sortexpr, } /* + * Show the window definition for a WindowAgg node. + */ +static void +show_window_def(WindowAggState *planstate, List *ancestors, ExplainState *es) +{ + WindowAgg *wagg = (WindowAgg *) planstate->ss.ps.plan; + StringInfoData wbuf; + bool needspace = false; + + initStringInfo(&wbuf); + appendStringInfo(&wbuf, "%s AS (", quote_identifier(wagg->winname)); + + /* The key columns refer to the tlist of the child plan */ + ancestors = lcons(wagg, ancestors); + if (wagg->partNumCols > 0) + { + appendStringInfoString(&wbuf, "PARTITION BY "); + show_window_keys(&wbuf, outerPlanState(planstate), + wagg->partNumCols, wagg->partColIdx, + ancestors, es); + needspace = true; + } + if (wagg->ordNumCols > 0) + { + if (needspace) + appendStringInfoChar(&wbuf, ' '); + appendStringInfoString(&wbuf, "ORDER BY "); + show_window_keys(&wbuf, outerPlanState(planstate), + wagg->ordNumCols, wagg->ordColIdx, + ancestors, es); + needspace = true; + } + ancestors = list_delete_first(ancestors); + if (wagg->frameOptions & FRAMEOPTION_NONDEFAULT) + { + List *context; + bool useprefix; + char *framestr; + + /* Set up deparsing context for possible frame expressions */ + context = set_deparse_context_plan(es->deparse_cxt, + (Plan *) wagg, + ancestors); + useprefix = (es->rtable_size > 1 || es->verbose); + framestr = get_window_frame_options_for_explain(wagg->frameOptions, + wagg->startOffset, + wagg->endOffset, + context, + useprefix); + if (needspace) + appendStringInfoChar(&wbuf, ' '); + appendStringInfoString(&wbuf, framestr); + pfree(framestr); + } + appendStringInfoChar(&wbuf, ')'); + ExplainPropertyText("Window", wbuf.data, es); + pfree(wbuf.data); +} + +/* + * Append the keys of a window's PARTITION BY or ORDER BY clause to buf. + * We can't use show_sort_group_keys for this because that's too opinionated + * about how the result will be displayed. + * Note that the "planstate" node should be the WindowAgg's child. + */ +static void +show_window_keys(StringInfo buf, PlanState *planstate, + int nkeys, AttrNumber *keycols, + List *ancestors, ExplainState *es) +{ + Plan *plan = planstate->plan; + List *context; + bool useprefix; + + /* Set up deparsing context */ + context = set_deparse_context_plan(es->deparse_cxt, + plan, + ancestors); + useprefix = (es->rtable_size > 1 || es->verbose); + + for (int keyno = 0; keyno < nkeys; keyno++) + { + /* find key expression in tlist */ + AttrNumber keyresno = keycols[keyno]; + TargetEntry *target = get_tle_by_resno(plan->targetlist, + keyresno); + char *exprstr; + + if (!target) + elog(ERROR, "no tlist entry for key %d", keyresno); + /* Deparse the expression, showing any top-level cast */ + exprstr = deparse_expression((Node *) target->expr, context, + useprefix, true); + if (keyno > 0) + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, exprstr); + pfree(exprstr); + + /* + * We don't attempt to provide sort order information because + * WindowAgg carries equality operators not comparison operators; + * compare show_agg_keys. + */ + } +} + +/* * Show information on storage method and maximum memory/disk space used. */ static void |