yaml.explain.v3.1.patch
application/octet-stream
Filename: yaml.explain.v3.1.patch
Type: application/octet-stream
Part: 0
Message:
Re: Add YAML option to explain
Patch
Format: context
Series: patch v3
| File | + | − |
|---|---|---|
| contrib/auto_explain/auto_explain.c | 1 | 0 |
| doc/src/sgml/auto-explain.sgml | 1 | 1 |
| doc/src/sgml/ref/explain.sgml | 3 | 3 |
| doc/src/sgml/release-8.5.sgml | 1 | 1 |
| src/backend/commands/explain.c | 101 | 0 |
| src/include/commands/explain.h | 2 | 1 |
diff -cprN head/contrib/auto_explain/auto_explain.c work/contrib/auto_explain/auto_explain.c
*** head/contrib/auto_explain/auto_explain.c 2009-08-10 14:46:49.000000000 +0900
--- work/contrib/auto_explain/auto_explain.c 2009-11-30 11:54:52.313491403 +0900
*************** static const struct config_enum_entry fo
*** 29,34 ****
--- 29,35 ----
{"text", EXPLAIN_FORMAT_TEXT, false},
{"xml", EXPLAIN_FORMAT_XML, false},
{"json", EXPLAIN_FORMAT_JSON, false},
+ {"yaml", EXPLAIN_FORMAT_YAML, false},
{NULL, 0, false}
};
diff -cprN head/doc/src/sgml/auto-explain.sgml work/doc/src/sgml/auto-explain.sgml
*** head/doc/src/sgml/auto-explain.sgml 2009-08-10 14:46:50.000000000 +0900
--- work/doc/src/sgml/auto-explain.sgml 2009-11-30 11:54:52.314487423 +0900
*************** LOAD 'auto_explain';
*** 114,120 ****
<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.
Only superusers can change this setting.
</para>
</listitem>
--- 114,120 ----
<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>,
! <literal>json</literal>, and <literal>yaml</literal>. The default is text.
Only superusers can change this setting.
</para>
</listitem>
diff -cprN head/doc/src/sgml/ref/explain.sgml work/doc/src/sgml/ref/explain.sgml
*** head/doc/src/sgml/ref/explain.sgml 2009-08-10 14:46:50.000000000 +0900
--- work/doc/src/sgml/ref/explain.sgml 2009-11-30 11:54:52.314487423 +0900
*************** PostgreSQL documentation
*** 31,37 ****
<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 ] [ VERBOSE ] <replaceable class="parameter">statement</replaceable>
</synopsis>
</refsynopsisdiv>
--- 31,37 ----
<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 | YAML } } [, ...] ) ] <replaceable class="parameter">statement</replaceable>
EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replaceable>
</synopsis>
</refsynopsisdiv>
*************** ROLLBACK;
*** 143,150 ****
<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
format, but is easier for programs to parse. This parameter defaults to
<literal>TEXT</literal>.
</para>
--- 143,150 ----
<term><literal>FORMAT</literal></term>
<listitem>
<para>
! 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 -cprN head/doc/src/sgml/release-8.5.sgml work/doc/src/sgml/release-8.5.sgml
*** head/doc/src/sgml/release-8.5.sgml 2009-11-27 06:20:12.000000000 +0900
--- work/doc/src/sgml/release-8.5.sgml 2009-11-30 11:54:52.314487423 +0900
***************
*** 176,182 ****
</listitem>
<listitem>
<para>
! EXPLAIN allows output of plans in XML or JSON format for automated
processing of explain plans by analysis or visualization tools.
</para>
</listitem>
--- 176,182 ----
</listitem>
<listitem>
<para>
! 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 -cprN head/src/backend/commands/explain.c work/src/backend/commands/explain.c
*** head/src/backend/commands/explain.c 2009-11-05 07:26:04.000000000 +0900
--- work/src/backend/commands/explain.c 2009-11-30 12:23:01.926467595 +0900
*************** static void ExplainBeginOutput(ExplainSt
*** 95,101 ****
--- 95,103 ----
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);
/*
*************** ExplainQuery(ExplainStmt *stmt, const ch
*** 135,140 ****
--- 137,144 ----
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),
*************** ExplainPropertyList(const char *qlabel,
*** 1537,1542 ****
--- 1541,1559 ----
}
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;
}
}
*************** ExplainProperty(const char *qlabel, cons
*** 1584,1589 ****
--- 1601,1615 ----
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;
}
}
*************** ExplainOpenGroup(const char *objtype, co
*** 1668,1673 ****
--- 1694,1714 ----
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;
}
}
*************** ExplainCloseGroup(const char *objtype, c
*** 1697,1702 ****
--- 1738,1748 ----
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;
}
}
*************** ExplainDummyGroup(const char *objtype, c
*** 1729,1734 ****
--- 1775,1787 ----
}
escape_json(es->str, objtype);
break;
+
+ case EXPLAIN_FORMAT_YAML:
+ ExplainYAMLLineStarting(es);
+ if (labelname)
+ appendStringInfo(es->str, "%s:", labelname);
+ appendStringInfoString(es->str, objtype);
+ break;
}
}
*************** ExplainBeginOutput(ExplainState *es)
*** 1759,1764 ****
--- 1812,1821 ----
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;
}
}
*************** ExplainEndOutput(ExplainState *es)
*** 1784,1789 ****
--- 1841,1850 ----
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;
}
}
*************** ExplainSeparatePlans(ExplainState *es)
*** 1796,1801 ****
--- 1857,1863 ----
switch (es->format)
{
case EXPLAIN_FORMAT_TEXT:
+ case EXPLAIN_FORMAT_YAML:
/* add a blank line */
appendStringInfoChar(es->str, '\n');
break;
*************** ExplainJSONLineEnding(ExplainState *es)
*** 1859,1864 ****
--- 1921,1945 ----
}
/*
+ * 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
*************** escape_json(StringInfo buf, const char *
*** 1902,1904 ****
--- 1983,2005 ----
}
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 -cprN head/src/include/commands/explain.h work/src/include/commands/explain.h
*** head/src/include/commands/explain.h 2009-08-10 14:46:50.000000000 +0900
--- work/src/include/commands/explain.h 2009-11-30 11:54:52.315490662 +0900
*************** typedef enum ExplainFormat
*** 19,25 ****
{
EXPLAIN_FORMAT_TEXT,
EXPLAIN_FORMAT_XML,
! EXPLAIN_FORMAT_JSON
} ExplainFormat;
typedef struct ExplainState
--- 19,26 ----
{
EXPLAIN_FORMAT_TEXT,
EXPLAIN_FORMAT_XML,
! EXPLAIN_FORMAT_JSON,
! EXPLAIN_FORMAT_YAML
} ExplainFormat;
typedef struct ExplainState