aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/auto_explain/auto_explain.c3
-rw-r--r--doc/src/sgml/auto-explain.sgml4
-rw-r--r--doc/src/sgml/ref/explain.sgml8
-rw-r--r--doc/src/sgml/release-8.5.sgml4
-rw-r--r--src/backend/commands/explain.c103
-rw-r--r--src/include/commands/explain.h5
6 files changed, 115 insertions, 12 deletions
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c
index 6d3435be1f7..531f0765254 100644
--- a/contrib/auto_explain/auto_explain.c
+++ b/contrib/auto_explain/auto_explain.c
@@ -6,7 +6,7 @@
* Copyright (c) 2008-2009, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/auto_explain/auto_explain.c,v 1.7 2009/08/10 05:46:49 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/auto_explain/auto_explain.c,v 1.8 2009/12/11 01:33:35 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,6 +29,7 @@ static const struct config_enum_entry format_options[] = {
{"text", EXPLAIN_FORMAT_TEXT, false},
{"xml", EXPLAIN_FORMAT_XML, false},
{"json", EXPLAIN_FORMAT_JSON, false},
+ {"yaml", EXPLAIN_FORMAT_YAML, false},
{NULL, 0, false}
};
diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml
index 72487f944ce..39c7bc20f59 100644
--- a/doc/src/sgml/auto-explain.sgml
+++ b/doc/src/sgml/auto-explain.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/auto-explain.sgml,v 1.4 2009/08/10 05:46:50 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/auto-explain.sgml,v 1.5 2009/12/11 01:33:35 adunstan Exp $ -->
<sect1 id="auto-explain">
<title>auto_explain</title>
@@ -114,7 +114,7 @@ LOAD 'auto_explain';
<varname>auto_explain.log_format</varname> selects the
<command>EXPLAIN</> output format to be used.
The allowed values are <literal>text</literal>, <literal>xml</literal>,
- and <literal>json</literal>. The default is text.
+ <literal>json</literal>, and <literal>yaml</literal>. The default is text.
Only superusers can change this setting.
</para>
</listitem>
diff --git a/doc/src/sgml/ref/explain.sgml b/doc/src/sgml/ref/explain.sgml
index 9670bd06f19..4de5a4aba63 100644
--- a/doc/src/sgml/ref/explain.sgml
+++ b/doc/src/sgml/ref/explain.sgml
@@ -1,5 +1,5 @@
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/explain.sgml,v 1.46 2009/08/10 05:46:50 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/explain.sgml,v 1.47 2009/12/11 01:33:35 adunstan Exp $
PostgreSQL documentation
-->
@@ -31,7 +31,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
-EXPLAIN [ ( { ANALYZE <replaceable class="parameter">boolean</replaceable> | VERBOSE <replaceable class="parameter">boolean</replaceable> | COSTS <replaceable class="parameter">boolean</replaceable> | FORMAT { TEXT | XML | JSON } } [, ...] ) ] <replaceable class="parameter">statement</replaceable>
+EXPLAIN [ ( { ANALYZE <replaceable class="parameter">boolean</replaceable> | VERBOSE <replaceable class="parameter">boolean</replaceable> | COSTS <replaceable class="parameter">boolean</replaceable> | FORMAT { TEXT | XML | JSON | YAML } } [, ...] ) ] <replaceable class="parameter">statement</replaceable>
EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replaceable>
</synopsis>
</refsynopsisdiv>
@@ -143,8 +143,8 @@ ROLLBACK;
<term><literal>FORMAT</literal></term>
<listitem>
<para>
- Specify the output format, which can be TEXT, XML, or JSON.
- XML or JSON output contains the same information as the text output
+ Specify the output format, which can be TEXT, XML, JSON, or YAML.
+ Non-text output contains the same information as the text output
format, but is easier for programs to parse. This parameter defaults to
<literal>TEXT</literal>.
</para>
diff --git a/doc/src/sgml/release-8.5.sgml b/doc/src/sgml/release-8.5.sgml
index caca7508250..f95b35505c3 100644
--- a/doc/src/sgml/release-8.5.sgml
+++ b/doc/src/sgml/release-8.5.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/release-8.5.sgml,v 1.8 2009/11/26 21:20:12 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/release-8.5.sgml,v 1.9 2009/12/11 01:33:35 adunstan Exp $ -->
<sect1 id="release-8-5">
<title>Release 8.5alpha2</title>
@@ -176,7 +176,7 @@
</listitem>
<listitem>
<para>
- EXPLAIN allows output of plans in XML or JSON format for automated
+ EXPLAIN allows output of plans in XML, JSON, or YAML format for automated
processing of explain plans by analysis or visualization tools.
</para>
</listitem>
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 21fa3add4f6..0970723a6de 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.193 2009/11/04 22:26:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.194 2009/12/11 01:33:35 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@@ -95,7 +95,9 @@ static void ExplainBeginOutput(ExplainState *es);
static void ExplainEndOutput(ExplainState *es);
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es);
static void ExplainJSONLineEnding(ExplainState *es);
+static void ExplainYAMLLineStarting(ExplainState *es);
static void escape_json(StringInfo buf, const char *str);
+static void escape_yaml(StringInfo buf, const char *str);
/*
@@ -135,6 +137,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
es.format = EXPLAIN_FORMAT_XML;
else if (strcmp(p, "json") == 0)
es.format = EXPLAIN_FORMAT_JSON;
+ else if (strcmp(p, "yaml") == 0)
+ es.format = EXPLAIN_FORMAT_YAML;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1537,6 +1541,19 @@ ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
}
appendStringInfoChar(es->str, ']');
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ ExplainYAMLLineStarting(es);
+ escape_yaml(es->str, qlabel);
+ appendStringInfoChar(es->str, ':');
+ foreach(lc, data)
+ {
+ appendStringInfoChar(es->str, '\n');
+ appendStringInfoSpaces(es->str, es->indent * 2 + 2);
+ appendStringInfoString(es->str, "- ");
+ escape_yaml(es->str, (const char *) lfirst(lc));
+ }
+ break;
}
}
@@ -1584,6 +1601,15 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
else
escape_json(es->str, value);
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ ExplainYAMLLineStarting(es);
+ appendStringInfo(es->str, "%s: ", qlabel);
+ if (numeric)
+ appendStringInfoString(es->str, value);
+ else
+ escape_yaml(es->str, value);
+ break;
}
}
@@ -1668,6 +1694,21 @@ ExplainOpenGroup(const char *objtype, const char *labelname,
es->grouping_stack = lcons_int(0, es->grouping_stack);
es->indent++;
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ ExplainYAMLLineStarting(es);
+ if (labelname)
+ {
+ appendStringInfo(es->str, "%s:", labelname);
+ es->grouping_stack = lcons_int(1, es->grouping_stack);
+ }
+ else
+ {
+ appendStringInfoChar(es->str, '-');
+ es->grouping_stack = lcons_int(0, es->grouping_stack);
+ }
+ es->indent++;
+ break;
}
}
@@ -1697,6 +1738,11 @@ ExplainCloseGroup(const char *objtype, const char *labelname,
appendStringInfoChar(es->str, labeled ? '}' : ']');
es->grouping_stack = list_delete_first(es->grouping_stack);
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ es->indent--;
+ es->grouping_stack = list_delete_first(es->grouping_stack);
+ break;
}
}
@@ -1729,6 +1775,13 @@ ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
}
escape_json(es->str, objtype);
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ ExplainYAMLLineStarting(es);
+ if (labelname)
+ appendStringInfo(es->str, "%s:", labelname);
+ appendStringInfoString(es->str, objtype);
+ break;
}
}
@@ -1759,6 +1812,10 @@ ExplainBeginOutput(ExplainState *es)
es->grouping_stack = lcons_int(0, es->grouping_stack);
es->indent++;
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ es->grouping_stack = lcons_int(0, es->grouping_stack);
+ break;
}
}
@@ -1784,6 +1841,10 @@ ExplainEndOutput(ExplainState *es)
appendStringInfoString(es->str, "\n]");
es->grouping_stack = list_delete_first(es->grouping_stack);
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ es->grouping_stack = list_delete_first(es->grouping_stack);
+ break;
}
}
@@ -1796,6 +1857,7 @@ ExplainSeparatePlans(ExplainState *es)
switch (es->format)
{
case EXPLAIN_FORMAT_TEXT:
+ case EXPLAIN_FORMAT_YAML:
/* add a blank line */
appendStringInfoChar(es->str, '\n');
break;
@@ -1859,6 +1921,25 @@ ExplainJSONLineEnding(ExplainState *es)
}
/*
+ * Indent a YAML line.
+ */
+static void
+ExplainYAMLLineStarting(ExplainState *es)
+{
+ Assert(es->format == EXPLAIN_FORMAT_YAML);
+ if (linitial_int(es->grouping_stack) == 0)
+ {
+ appendStringInfoChar(es->str, ' ');
+ linitial_int(es->grouping_stack) = 1;
+ }
+ else
+ {
+ appendStringInfoChar(es->str, '\n');
+ appendStringInfoSpaces(es->str, es->indent * 2);
+ }
+}
+
+/*
* Produce a JSON string literal, properly escaping characters in the text.
*/
static void
@@ -1902,3 +1983,23 @@ escape_json(StringInfo buf, const char *str)
}
appendStringInfoCharMacro(buf, '\"');
}
+
+/*
+ * YAML is a superset of JSON: if we find quotable characters, we call escape_json
+ */
+static void
+escape_yaml(StringInfo buf, const char *str)
+{
+ const char *p;
+
+ for (p = str; *p; p++)
+ {
+ if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p))
+ {
+ escape_json(buf, str);
+ return;
+ }
+ }
+
+ appendStringInfo(buf, "%s", str);
+}
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index fa2c8aac668..7137a7ab41e 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/commands/explain.h,v 1.41 2009/08/10 05:46:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/explain.h,v 1.42 2009/12/11 01:33:35 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,7 +19,8 @@ typedef enum ExplainFormat
{
EXPLAIN_FORMAT_TEXT,
EXPLAIN_FORMAT_XML,
- EXPLAIN_FORMAT_JSON
+ EXPLAIN_FORMAT_JSON,
+ EXPLAIN_FORMAT_YAML
} ExplainFormat;
typedef struct ExplainState