From: Tom Lane Date: Wed, 29 Jun 2016 22:51:20 +0000 (-0400) Subject: Fix some infelicities in EXPLAIN output for parallel query plans. X-Git-Tag: REL9_6_BETA3~83 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8ebb69f85445177575684a0ba5cfedda8d840a91;p=postgresql Fix some infelicities in EXPLAIN output for parallel query plans. In non-text output formats, parallelized aggregates were reporting "Partial" or "Finalize" as a field named "Operation", which might be all right in the absence of any context --- but other plan node types use that field to report SQL-visible semantics, such as Select/Insert/Update/Delete. So that naming choice didn't seem good to me. I changed it to "Partial Mode". Also, the field did not appear at all for a non-parallelized Agg plan node, which is contrary to expectation in non-text formats. We're notionally producing objects that conform to a schema, so the set of fields for a given node type and EXPLAIN mode should be well-defined. I set it up to fill in "Simple" in such cases. Other fields that were added for parallel query, namely "Parallel Aware" and Gather's "Single Copy", had not gotten the word on that point either. Make them appear always in non-text output. Also, the latter two fields were nominally producing boolean output, but were getting it wrong, because bool values shouldn't be quoted in JSON or YAML. Somehow we'd not needed an ExplainPropertyBool formatting subroutine before 9.6; but now we do, so invent it. Discussion: <16002.1466972724@sss.pgh.pa.us> --- diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 319dd8e224..9873022bf8 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -807,6 +807,7 @@ ExplainNode(PlanState *planstate, List *ancestors, const char *pname; /* node type name for text output */ const char *sname; /* node type name for non-text output */ const char *strategy = NULL; + const char *partialmode = NULL; const char *operation = NULL; const char *custom_name = NULL; int save_indent = es->indent; @@ -943,15 +944,10 @@ ExplainNode(PlanState *planstate, List *ancestors, pname = sname = "Group"; break; case T_Agg: - sname = "Aggregate"; { Agg *agg = (Agg *) plan; - if (DO_AGGSPLIT_SKIPFINAL(agg->aggsplit)) - operation = "Partial"; - else if (DO_AGGSPLIT_COMBINE(agg->aggsplit)) - operation = "Finalize"; - + sname = "Aggregate"; switch (agg->aggstrategy) { case AGG_PLAIN: @@ -972,8 +968,18 @@ ExplainNode(PlanState *planstate, List *ancestors, break; } - if (operation != NULL) - pname = psprintf("%s %s", operation, pname); + if (DO_AGGSPLIT_SKIPFINAL(agg->aggsplit)) + { + partialmode = "Partial"; + pname = psprintf("%s %s", partialmode, pname); + } + else if (DO_AGGSPLIT_COMBINE(agg->aggsplit)) + { + partialmode = "Finalize"; + pname = psprintf("%s %s", partialmode, pname); + } + else + partialmode = "Simple"; } break; case T_WindowAgg: @@ -1042,6 +1048,8 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyText("Node Type", sname, es); if (strategy) ExplainPropertyText("Strategy", strategy, es); + if (partialmode) + ExplainPropertyText("Partial Mode", partialmode, es); if (operation) ExplainPropertyText("Operation", operation, es); if (relationship) @@ -1050,8 +1058,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyText("Subplan Name", plan_name, es); if (custom_name) ExplainPropertyText("Custom Plan Provider", custom_name, es); - if (plan->parallel_aware) - ExplainPropertyText("Parallel Aware", "true", es); + ExplainPropertyBool("Parallel Aware", plan->parallel_aware, es); } switch (nodeTag(plan)) @@ -1349,10 +1356,8 @@ ExplainNode(PlanState *planstate, List *ancestors, ExplainPropertyInteger("Workers Launched", nworkers, es); } - if (gather->single_copy) - ExplainPropertyText("Single Copy", - gather->single_copy ? "true" : "false", - es); + if (gather->single_copy || es->format != EXPLAIN_FORMAT_TEXT) + ExplainPropertyBool("Single Copy", gather->single_copy, es); } break; case T_FunctionScan: @@ -3031,6 +3036,15 @@ ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ExplainProperty(qlabel, buf, true, es); } +/* + * Explain a bool-valued property. + */ +void +ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es) +{ + ExplainProperty(qlabel, value ? "true" : "false", true, es); +} + /* * Open a group of related objects. * diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h index 904925d712..2e48f0f233 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h @@ -93,5 +93,7 @@ extern void ExplainPropertyLong(const char *qlabel, long value, ExplainState *es); extern void ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ExplainState *es); +extern void ExplainPropertyBool(const char *qlabel, bool value, + ExplainState *es); #endif /* EXPLAIN_H */ diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out index e5c8b4aaac..6f4ec867d9 100644 --- a/src/test/regress/expected/insert_conflict.out +++ b/src/test/regress/expected/insert_conflict.out @@ -205,6 +205,7 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Plan": { + "Node Type": "ModifyTable", + "Operation": "Insert", + + "Parallel Aware": false, + "Relation Name": "insertconflicttest", + "Alias": "insertconflicttest", + "Conflict Resolution": "UPDATE", + @@ -213,7 +214,8 @@ explain (costs off, format json) insert into insertconflicttest values (0, 'Bilb "Plans": [ + { + "Node Type": "Result", + - "Parent Relationship": "Member" + + "Parent Relationship": "Member", + + "Parallel Aware": false + } + ] + } +