Commit ff499613 authored by Robert Haas's avatar Robert Haas

Several fixes for EXPLAIN (FORMAT YAML), plus one for EXPLAIN (FORMAT JSON).

ExplainSeparatePlans() was busted for both JSON and YAML output - the present
code is a holdover from the original version of my machine-readable explain
patch, which didn't have the grouping_stack machinery.  Also, fix an odd
distribution of labor between ExplainBeginGroup() and ExplainYAMLLineStarting()
when marking lists with "- ", with each providing one character.  This broke
the output format for multi-query statements.  Also, fix ExplainDummyGroup()
for the YAML output format.

Along the way, make the YAML format use escape_yaml() in situations where the
JSON format uses escape_json().  Right now, it doesn't matter because all the
values are known not to need escaping, but it seems safer this way.  Finally,
I added some comments to better explain what the YAML output format is doing.

Greg Sabino Mullane reported the issues with multi-query statements.
Analysis and remaining cleanups by me.
parent 3dfe7e8e
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.196 2009/12/15 04:57:47 rhaas Exp $ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.197 2009/12/16 22:16:16 rhaas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1694,9 +1694,6 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric, ...@@ -1694,9 +1694,6 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
case EXPLAIN_FORMAT_YAML: case EXPLAIN_FORMAT_YAML:
ExplainYAMLLineStarting(es); ExplainYAMLLineStarting(es);
appendStringInfo(es->str, "%s: ", qlabel); appendStringInfo(es->str, "%s: ", qlabel);
if (numeric)
appendStringInfoString(es->str, value);
else
escape_yaml(es->str, value); escape_yaml(es->str, value);
break; break;
} }
...@@ -1785,15 +1782,23 @@ ExplainOpenGroup(const char *objtype, const char *labelname, ...@@ -1785,15 +1782,23 @@ ExplainOpenGroup(const char *objtype, const char *labelname,
break; break;
case EXPLAIN_FORMAT_YAML: case EXPLAIN_FORMAT_YAML:
/*
* In YAML format, the grouping stack is an integer list. 0 means
* we've emitted nothing at this grouping level AND this grouping
* level is unlabelled and must be marked with "- ". See
* ExplainYAMLLineStarting().
*/
ExplainYAMLLineStarting(es); ExplainYAMLLineStarting(es);
if (labelname) if (labelname)
{ {
appendStringInfo(es->str, "%s:", labelname); escape_yaml(es->str, labelname);
appendStringInfoChar(es->str, ':');
es->grouping_stack = lcons_int(1, es->grouping_stack); es->grouping_stack = lcons_int(1, es->grouping_stack);
} }
else else
{ {
appendStringInfoChar(es->str, '-'); appendStringInfoString(es->str, "- ");
es->grouping_stack = lcons_int(0, es->grouping_stack); es->grouping_stack = lcons_int(0, es->grouping_stack);
} }
es->indent++; es->indent++;
...@@ -1868,8 +1873,15 @@ ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es) ...@@ -1868,8 +1873,15 @@ ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
case EXPLAIN_FORMAT_YAML: case EXPLAIN_FORMAT_YAML:
ExplainYAMLLineStarting(es); ExplainYAMLLineStarting(es);
if (labelname) if (labelname)
appendStringInfo(es->str, "%s:", labelname); {
appendStringInfoString(es->str, objtype); escape_yaml(es->str, labelname);
appendStringInfoString(es->str, ": ");
}
else
{
appendStringInfoString(es->str, "- ");
}
escape_yaml(es->str, objtype);
break; break;
} }
} }
...@@ -1946,18 +1958,14 @@ ExplainSeparatePlans(ExplainState *es) ...@@ -1946,18 +1958,14 @@ ExplainSeparatePlans(ExplainState *es)
switch (es->format) switch (es->format)
{ {
case EXPLAIN_FORMAT_TEXT: case EXPLAIN_FORMAT_TEXT:
case EXPLAIN_FORMAT_YAML:
/* add a blank line */ /* add a blank line */
appendStringInfoChar(es->str, '\n'); appendStringInfoChar(es->str, '\n');
break; break;
case EXPLAIN_FORMAT_XML: case EXPLAIN_FORMAT_XML:
/* nothing to do */
break;
case EXPLAIN_FORMAT_JSON: case EXPLAIN_FORMAT_JSON:
/* must have a comma between array elements */ case EXPLAIN_FORMAT_YAML:
appendStringInfoChar(es->str, ','); /* nothing to do */
break; break;
} }
} }
...@@ -2011,6 +2019,12 @@ ExplainJSONLineEnding(ExplainState *es) ...@@ -2011,6 +2019,12 @@ ExplainJSONLineEnding(ExplainState *es)
/* /*
* Indent a YAML line. * Indent a YAML line.
*
* YAML lines are ordinarily indented by two spaces per indentation level.
* The text emitted for each property begins just prior to the preceding
* line-break, except for the first property in an unlabelled group, for which
* it begins immediately after the "- " that introduces the group. The first
* property of the group appears on the same line as the opening "- ".
*/ */
static void static void
ExplainYAMLLineStarting(ExplainState *es) ExplainYAMLLineStarting(ExplainState *es)
...@@ -2018,7 +2032,6 @@ ExplainYAMLLineStarting(ExplainState *es) ...@@ -2018,7 +2032,6 @@ ExplainYAMLLineStarting(ExplainState *es)
Assert(es->format == EXPLAIN_FORMAT_YAML); Assert(es->format == EXPLAIN_FORMAT_YAML);
if (linitial_int(es->grouping_stack) == 0) if (linitial_int(es->grouping_stack) == 0)
{ {
appendStringInfoChar(es->str, ' ');
linitial_int(es->grouping_stack) = 1; linitial_int(es->grouping_stack) = 1;
} }
else else
...@@ -2074,7 +2087,8 @@ escape_json(StringInfo buf, const char *str) ...@@ -2074,7 +2087,8 @@ escape_json(StringInfo buf, const char *str)
} }
/* /*
* YAML is a superset of JSON: if we find quotable characters, we call escape_json * YAML is a superset of JSON: if we find quotable characters, we call
* escape_json. If not, we emit the property unquoted for better readability.
*/ */
static void static void
escape_yaml(StringInfo buf, const char *str) escape_yaml(StringInfo buf, const char *str)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment