Thread: explain root element for auto-explain

explain root element for auto-explain

From
Andrew Dunstan
Date:
The attached tiny patch sets the <explain> root element for auto-explain
XML output, so it looks something like this:

    <explain xmlns="http://www.postgresql.org/2009/explain">
      <Plan>
        <Node-Type>Result</Node-Type>
        <Startup-Cost>0.00</Startup-Cost>
        <Total-Cost>0.01</Total-Cost>
        <Plan-Rows>1</Plan-Rows>
        <Plan-Width>0</Plan-Width>
      </Plan>
    </explain>

The JSON output looks like this:

    [
      "Plan": {
        "Node Type": "Result",
        "Startup Cost": 0.00,
        "Total Cost": 0.01,
        "Plan Rows": 1,
        "Plan Width": 0
      }
    ]

This is worth doing in itself in the XML case for reasons previously
explained, but it also makes it relatively easy to add a Query-Text node
or some such to the structured output, which is very much worth having,
and would be my next proposed step.

cheers

andrew
Index: contrib/auto_explain/auto_explain.c
===================================================================
RCS file: /cvsroot/pgsql/contrib/auto_explain/auto_explain.c,v
retrieving revision 1.7
diff -c -r1.7 auto_explain.c
*** contrib/auto_explain/auto_explain.c    10 Aug 2009 05:46:49 -0000    1.7
--- contrib/auto_explain/auto_explain.c    17 Aug 2009 21:19:08 -0000
***************
*** 222,228 ****
--- 222,230 ----
              es.verbose = auto_explain_log_verbose;
              es.format = auto_explain_log_format;

+             ExplainBeginOutput(&es);
              ExplainPrintPlan(&es, queryDesc);
+             ExplainEndOutput(&es);

              /* Remove last line break */
              if (es.str->len > 0 && es.str->data[es.str->len - 1] == '\n')
Index: src/backend/commands/explain.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/explain.c,v
retrieving revision 1.189
diff -c -r1.189 explain.c
*** src/backend/commands/explain.c    10 Aug 2009 05:46:50 -0000    1.189
--- src/backend/commands/explain.c    17 Aug 2009 21:19:09 -0000
***************
*** 91,98 ****
                   bool labeled, ExplainState *es);
  static void ExplainDummyGroup(const char *objtype, const char *labelname,
                                ExplainState *es);
- 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 escape_json(StringInfo buf, const char *str);
--- 91,96 ----
***************
*** 1712,1718 ****
   * This is just enough different from processing a subgroup that we need
   * a separate pair of subroutines.
   */
! static void
  ExplainBeginOutput(ExplainState *es)
  {
      switch (es->format)
--- 1710,1716 ----
   * This is just enough different from processing a subgroup that we need
   * a separate pair of subroutines.
   */
! void
  ExplainBeginOutput(ExplainState *es)
  {
      switch (es->format)
***************
*** 1739,1745 ****
  /*
   * Emit the end-of-output boilerplate.
   */
! static void
  ExplainEndOutput(ExplainState *es)
  {
      switch (es->format)
--- 1737,1743 ----
  /*
   * Emit the end-of-output boilerplate.
   */
! void
  ExplainEndOutput(ExplainState *es)
  {
      switch (es->format)
Index: src/include/commands/explain.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/commands/explain.h,v
retrieving revision 1.41
diff -c -r1.41 explain.h
*** src/include/commands/explain.h    10 Aug 2009 05:46:50 -0000    1.41
--- src/include/commands/explain.h    17 Aug 2009 21:19:09 -0000
***************
*** 54,59 ****
--- 54,63 ----

  extern void ExplainInitState(ExplainState *es);

+ extern void ExplainBeginOutput(ExplainState *es);
+
+ extern void ExplainEndOutput(ExplainState *es);
+
  extern TupleDesc ExplainResultDesc(ExplainStmt *stmt);

  extern void ExplainOneUtility(Node *utilityStmt, ExplainState *es,

Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew.dunstan@pgexperts.com> writes:
> The attached tiny patch sets the <explain> root element for auto-explain 
> XML output, so it looks something like this:

This looks reasonable in itself, but it sort of begs the question on
two other things:

* what's the xmlns URL really going to be?

* what's the <Query> element in regular XML output good for?  And
shouldn't we make both explain and auto-explain either have that or not?

> The JSON output looks like this:

>     [
>       "Plan": {
>         "Node Type": "Result",
>         "Startup Cost": 0.00,
>         "Total Cost": 0.01,
>         "Plan Rows": 1,
>         "Plan Width": 0
>       }
>     ]

<squint> Bearing in mind that I know roughly nothing of JSON ... surely
the above is syntactically incorrect?  A labeled value should be within
{...} not [...].  I think this is closely related to the point about
<Query>, ie the same semantic nesting level is missing in both cases.
        regards, tom lane


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew.dunstan@pgexperts.com> writes:
>   
>> The attached tiny patch sets the <explain> root element for auto-explain 
>> XML output, so it looks something like this:
>>     
>
> This looks reasonable in itself, but it sort of begs the question on
> two other things:
>
> * what's the xmlns URL really going to be?
>   

By convention it refers to a place where you publish the schema for the 
document type, but it is in fact completely arbitrary, and can refer to 
a non-existant resource - as long as it is unique - it's just a 
namespace designator, and from an XML POV has no more semantic 
significance that a schema name does in SQL.

> * what's the <Query> element in regular XML output good for?  And
> shouldn't we make both explain and auto-explain either have that or not?
>
>   

and also, why isn't it present in the JSON output for either? We seem to 
have several places when we output an XML tag but not a corresponding 
named JSON node. Is that really a good idea?


>> The JSON output looks like this:
>>     
>
>   
>>     [
>>       "Plan": {
>>         "Node Type": "Result",
>>         "Startup Cost": 0.00,
>>         "Total Cost": 0.01,
>>         "Plan Rows": 1,
>>         "Plan Width": 0
>>       }
>>     ]
>>     
>
> <squint> Bearing in mind that I know roughly nothing of JSON ... surely
> the above is syntactically incorrect?  A labeled value should be within
> {...} not [...].  I think this is closely related to the point about
> <Query>, ie the same semantic nesting level is missing in both cases.
>   

Looks like it. <http://www.jsonlint.com/> is useful for checking such 
things.

Of course, the current JSON output from auto-explain (i.e. without the 
enclosing [ ] ) is also illegal, unlike the output from "explain (format 
json) select 1", which encloses the Plan node in { } inside the [ ],


cheers

andrew







Re: explain root element for auto-explain

From
Andrew Dunstan
Date:

Andrew Dunstan wrote:
>
>
> Tom Lane wrote:
>>
>>
>> * what's the xmlns URL really going to be?
>>   
>
> By convention it refers to a place where you publish the schema for 
> the document type, but it is in fact completely arbitrary, and can 
> refer to a non-existant resource - as long as it is unique - it's just 
> a namespace designator, and from an XML POV has no more semantic 
> significance that a schema name does in SQL.
>
>

One thing I definitely think we should do is to put the namespace URL in 
a header file. Think of it as being a bit like the catversion. 
Hardcoding it in explain.c doesn't seem like a good idea.

cheers

andrew


Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> One thing I definitely think we should do is to put the namespace URL in 
> a header file. Think of it as being a bit like the catversion. 
> Hardcoding it in explain.c doesn't seem like a good idea.

Well, it could at least be a #define, but what's the point of exposing
it in a header file --- what other code will use that file?
        regards, tom lane


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>   
>> One thing I definitely think we should do is to put the namespace URL in 
>> a header file. Think of it as being a bit like the catversion. 
>> Hardcoding it in explain.c doesn't seem like a good idea.
>>     
>
> Well, it could at least be a #define, but what's the point of exposing
> it in a header file --- what other code will use that file?
>
>             
>   

Good point. None right now I guess. But certainly a #define.

cheers

andrew


Re: explain root element for auto-explain

From
Magnus Hagander
Date:
On Tue, Aug 18, 2009 at 02:11, Andrew Dunstan<andrew@dunslane.net> wrote:
>
> Tom Lane wrote:
>>
>> Andrew Dunstan <andrew.dunstan@pgexperts.com> writes:
>>
>>>
>>> The attached tiny patch sets the <explain> root element for auto-explain
>>> XML output, so it looks something like this:
>>>
>>
>> This looks reasonable in itself, but it sort of begs the question on
>> two other things:
>>
>> * what's the xmlns URL really going to be?
>>
>
> By convention it refers to a place where you publish the schema for the
> document type, but it is in fact completely arbitrary, and can refer to a
> non-existant resource - as long as it is unique - it's just a namespace
> designator, and from an XML POV has no more semantic significance that a
> schema name does in SQL.

I'd suggest using a different namespace than www.postgresql.org, just
to be sure it won't conflict with some system we use in the future.
Perhaps http://schemas.postgresql.org/<whatever>? It doesn't actually
need to exist until we want to put anything there, but it mustn't
conflict with anything else.


-- Magnus HaganderMe: http://www.hagander.net/Work: http://www.redpill-linpro.com/


Re: explain root element for auto-explain

From
Bruce Momjian
Date:
Are we going to publish an XML DTD for EXPLAIN, or have we already?

---------------------------------------------------------------------------

Andrew Dunstan wrote:
> 
> The attached tiny patch sets the <explain> root element for auto-explain 
> XML output, so it looks something like this:
> 
>     <explain xmlns="http://www.postgresql.org/2009/explain">
>       <Plan>
>         <Node-Type>Result</Node-Type>
>         <Startup-Cost>0.00</Startup-Cost>
>         <Total-Cost>0.01</Total-Cost>
>         <Plan-Rows>1</Plan-Rows>
>         <Plan-Width>0</Plan-Width>
>       </Plan>
>     </explain>
> 
> The JSON output looks like this:
> 
>     [
>       "Plan": {
>         "Node Type": "Result",
>         "Startup Cost": 0.00,
>         "Total Cost": 0.01,
>         "Plan Rows": 1,
>         "Plan Width": 0
>       }
>     ]
> 
> This is worth doing in itself in the XML case for reasons previously 
> explained, but it also makes it relatively easy to add a Query-Text node 
> or some such to the structured output, which is very much worth having, 
> and would be my next proposed step.
> 
> cheers
> 
> andrew


> 
> -- 
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:
Bruce Momjian wrote:
> Are we going to publish an XML DTD for EXPLAIN, or have we already?

Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).

cheers

andrew



Re: explain root element for auto-explain

From
Bruce Momjian
Date:
Andrew Dunstan wrote:
> Bruce Momjian wrote:
> > Are we going to publish an XML DTD for EXPLAIN, or have we already?
> 
> Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).

OK, either one would be good.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + If your life is a hard drive, Christ can be your backup. +


Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Bruce Momjian wrote:
>> Are we going to publish an XML DTD for EXPLAIN, or have we already?

> Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).

+1 ... I asked for a spec for the output format before, and this would
do fine.
        regards, tom lane


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:

Andrew Dunstan wrote:
> Bruce Momjian wrote:
>> Are we going to publish an XML DTD for EXPLAIN, or have we already?
>
> Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).
>
>

Here is a RelaxNG spec which people might find a bit easier to read. It 
has been autocreated by a little tool called trang, that I used on a 
very large body of explain output that I produced by mangling the 
regression tests (and, incidentally, crashing the server in the result - 
I still have to chase that up).

I have a couple of questions, however. First, in that long list of 
alternatives for a Plan node, can any of them occur more than once? 
Second, we are using Item as a child of both Output and Sort-Key nodes. 
Are they really describing the same thing? And in any case, Item is a 
wonderfully non-informative name, as is Output, for that matter.

BTW - I know this requires tweaking - those xsd:NCName values will 
probably just become text, for example.

cheers

andrew


default namespace = "http://www.postgresql.org/2009/explain"

start =   element explain {     element Query {       Plan,       element Triggers { empty },       element
Total-Runtime{ xsd:decimal }     }   }
 
Plan = element Plan {   (element Actual-Loops { xsd:integer }    | element Actual-Rows { xsd:integer }    | element
Actual-Startup-Time{ xsd:decimal }    | element Actual-Total-Time { xsd:decimal }    | element Alias { text }    |
elementFilter { text }    | element Function-Name { xsd:NCName }    | element Hash-Cond { text }    | element
Index-Name{ xsd:NCName }    | element Join-Filter { text }    | element Join-Type { xsd:NCName }    | element
Merge-Cond{ text }    | element Node-Type { text }    | element One-Time-Filter { text }    | element Output { Item+ }
 | element Parent-Relationship { xsd:NCName }    | element Plan-Rows { xsd:integer }    | element Plan-Width {
xsd:integer}    | element Plans { Plan* }    | element Recheck-Cond { text }    | element Relation-Name { xsd:NCName }
 | element Scan-Direction { xsd:NCName }    | element Schema { xsd:NCName }    | element Sort-Key { Item+ }    |
elementSort-Method { text }    | element Sort-Space-Type { xsd:NCName }    | element Sort-Space-Used { xsd:integer }
|element Startup-Cost { xsd:decimal }    | element Strategy { xsd:NCName }    | element Subplan-Name { text }    |
elementTotal-Cost { xsd:decimal })*,   element Index-Cond { text }? }
 
Item = element Item { text }



Re: explain root element for auto-explain

From
Robert Haas
Date:
On Thu, Aug 20, 2009 at 9:30 AM, Andrew Dunstan<andrew@dunslane.net> wrote:
>
>
> Andrew Dunstan wrote:
>>
>> Bruce Momjian wrote:
>>>
>>> Are we going to publish an XML DTD for EXPLAIN, or have we already?
>>
>> Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).
>>
>>
>
> Here is a RelaxNG spec which people might find a bit easier to read. It has
> been autocreated by a little tool called trang, that I used on a very large
> body of explain output that I produced by mangling the regression tests

This is definitely easy to read, especially for XML.

> (and, incidentally, crashing the server in the result - I still have to
> chase that up).

Hmm.

> I have a couple of questions, however. First, in that long list of
> alternatives for a Plan node, can any of them occur more than once?

I don't think so.  But I also don't think Index-Cond should be treated
specially, as you have done here.

> Second,
> we are using Item as a child of both Output and Sort-Key nodes. Are they
> really describing the same thing? And in any case, Item is a wonderfully
> non-informative name, as is Output, for that matter.

Well, I can't help Output.  That's what 8.4-EXPLAIN calls it.  I do
think maybe it should be ripped out of EXPLAIN (VERBOSE) and made a
separate option.

Are they really the same thing?  Obviously not.  I just needed a way
to make a list of scalars in XML and I picked that for want of
creativity.

> BTW - I know this requires tweaking - those xsd:NCName values will probably
> just become text, for example.

As far as I'm concerned, you're already way ahead producing something
that fits on the screen.

...Robert


Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> I have a couple of questions, however. First, in that long list of 
> alternatives for a Plan node, can any of them occur more than once? 

No.

> Second, we are using Item as a child of both Output and Sort-Key nodes. 
> Are they really describing the same thing? And in any case, Item is a 
> wonderfully non-informative name, as is Output, for that matter.

They are both describing expressions.  I wanted to rename Item as Expr,
if you'll recall.  But I think we should have a concrete plan about
all the tweaks we want to make to the output schema before doing
anything, so I haven't pushed to change it immediately.

I don't see anything wrong with Output --- what else would you call the
output expressions of a node?
        regards, tom lane


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:
I wrote:
>
>
> Andrew Dunstan wrote:
>> Bruce Momjian wrote:
>>> Are we going to publish an XML DTD for EXPLAIN, or have we already?
>>
>> Not a DTD, but I am working on an XML Schema (DTDs are a bit yesterday).
>>
>>
>
> Here is a RelaxNG spec which people might find a bit easier to read. 
> It has been autocreated by a little tool called trang, that I used on 
> a very large body of explain output that I produced by mangling the 
> regression tests (and, incidentally, crashing the server in the result 
> - I still have to chase that up).


Updated version with more complete information (regression crash was due 
to my bad script).

cheers

andrew


default namespace = "http://www.postgresql.org/2009/explain"

start =   element explain {     element Query {       Plan,       Triggers,       element Total-Runtime { xsd:decimal }
    }+  }
 
Plan = element Plan {   (element Actual-Loops { xsd:integer }    | element Actual-Rows { xsd:integer }    | element
Actual-Startup-Time{ xsd:decimal }    | element Actual-Total-Time { xsd:decimal }    | element Alias { text }    |
elementCTE-Name { text }    | element Command { text }    | element Filter { text }    | element Function-Name { text }
  | element Hash-Cond { text }    | element Index-Cond { text }    | element Index-Name { text }    | element
Join-Filter{ text }    | element Join-Type { text }    | element Merge-Cond { text }    | element Node-Type { text }
|element One-Time-Filter { text }    | element Output { Item* }    | element Parent-Relationship { text }    | element
Plan-Rows{ xsd:integer }    | element Plan-Width { xsd:integer }    | element Plans { Plan* }    | element Recheck-Cond
{text }    | element Relation-Name { text }    | element Scan-Direction { text }    | element Schema { text }    |
elementSort-Key { Item+ }    | element Sort-Method { text }    | element Sort-Space-Type { text }    | element
Sort-Space-Used{ xsd:integer }    | element Startup-Cost { xsd:decimal }    | element Strategy { text }    | element
Subplan-Name{ text }    | element Total-Cost { xsd:decimal },    | element TID-Cond { text }    )* }
 
Triggers = element Triggers {   element Trigger {     element Trigger-Name { text },     element Constraint-Name { text
}?,    element Relation { text },     element Time { xsd:decimal },     element Calls { xsd:integer }   }* }
 
Item = element Item { text }




Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Updated version with more complete information (regression crash was due 
> to my bad script).

I took a look through the source code to match it against this.  I found
that you missed a couple of possibilities: we have <Notify /> and
<Utility-Statement /> as alternatives to <Query> just below <explain>.

Also, it looks to me like <Item> is simply being used as an element
of lists (cf ExplainPropertyList); I was mistaken to equate it with
<Expr>.  I don't know XML well enough to understand if we really need
that syntactic detail, or if there's a more idiomatic way to treat
lists.

BTW, I wonder why <explain> doesn't have an init-cap like every other
node type name ...
        regards, tom lane


Re: explain root element for auto-explain

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>   
>> Updated version with more complete information (regression crash was due 
>> to my bad script).
>>     
>
> I took a look through the source code to match it against this.  I found
> that you missed a couple of possibilities: we have <Notify /> and
> <Utility-Statement /> as alternatives to <Query> just below <explain>.
>   


What causes those to happen? Here's how I mangled the regression tests 
to produce the output that this analysis was taken from:
   perl -spi.bak -e 
's/^(insert|update|select|delete|declare|execute|create table .* as) 
/explain (analyse true, verbose true, format xml) $1 /i;' *.sql

cheers

andrew




Re: explain root element for auto-explain

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Tom Lane wrote:
>> I took a look through the source code to match it against this.  I found
>> that you missed a couple of possibilities: we have <Notify /> and
>> <Utility-Statement /> as alternatives to <Query> just below <explain>.

> What causes those to happen?

You can get a <Notify> via explaining a command that's been affected
by a rule likeCREATE RULE foo ... DO ALSO NOTIFY foo;

I think the <Utility-Statement> case is not actually reachable code at
present.  NOTIFY is the only utility command that's allowed in CREATE
RULE, and auto-explain is hooked in in a place where it can't see
utility statements at all.  I suppose we could make EXPLAIN throw error
there, instead of printing a node type we'd have to document.
        regards, tom lane


Re: explain root element for auto-explain

From
Robert Haas
Date:
On Thu, Aug 20, 2009 at 12:40 PM, Andrew Dunstan<andrew@dunslane.net> wrote:
>
>
> Tom Lane wrote:
>>
>> Andrew Dunstan <andrew@dunslane.net> writes:
>>
>>>
>>> Updated version with more complete information (regression crash was due
>>> to my bad script).
>>>
>>
>> I took a look through the source code to match it against this.  I found
>> that you missed a couple of possibilities: we have <Notify /> and
>> <Utility-Statement /> as alternatives to <Query> just below <explain>.
>>
>
>
> What causes those to happen? Here's how I mangled the regression tests to
> produce the output that this analysis was taken from:
>
>   perl -spi.bak -e 's/^(insert|update|select|delete|declare|execute|create
> table .* as) /explain (analyse true, verbose true, format xml) $1 /i;' *.sql

CREATE RULE foo_notify AS ON UPDATE TO foo DO ALSO NOTIFY bob;

I am not sure that there's any way to get any other kind of utility
statement in there; I think that's just a safety valve in case someone
changes the rule mechanism and forgets to update EXPLAIN.

...Robert