Switch EXPLAIN to unaligned output for json/xml/yaml

Use unaligned output for multiple EXPLAIN queries using non-text format
in regression tests. With aligned output adding/removing explain fields
can be very disruptive, as it often modifies the whole block because of
padding. Unaligned output does not have this issue.

Author: Tomas Vondra <tomas@vondra.me>
Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Lukas Fittl <lukas@fittl.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/flat/a177a6dd-240b-455a-8f25-aca0b1c08c6e%40vondra.me
This commit is contained in:
Tomas Vondra 2026-04-07 22:12:26 +02:00
parent 4edd6036d6
commit 10d5a12a93
2 changed files with 151 additions and 152 deletions

View file

@ -93,164 +93,160 @@ select explain_filter('explain (analyze, buffers, format text) select * from int
Execution Time: N.N ms
(3 rows)
select explain_filter('explain (analyze, buffers, format xml) select * from int8_tbl i8');
explain_filter
--------------------------------------------------------
<explain xmlns="http://www.postgresql.org/N/explain"> +
<Query> +
<Plan> +
<Node-Type>Seq Scan</Node-Type> +
<Parallel-Aware>false</Parallel-Aware> +
<Async-Capable>false</Async-Capable> +
<Relation-Name>int8_tbl</Relation-Name> +
<Alias>i8</Alias> +
<Startup-Cost>N.N</Startup-Cost> +
<Total-Cost>N.N</Total-Cost> +
<Plan-Rows>N</Plan-Rows> +
<Plan-Width>N</Plan-Width> +
<Actual-Startup-Time>N.N</Actual-Startup-Time> +
<Actual-Total-Time>N.N</Actual-Total-Time> +
<Actual-Rows>N.N</Actual-Rows> +
<Actual-Loops>N</Actual-Loops> +
<Disabled>false</Disabled> +
<Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
<Shared-Read-Blocks>N</Shared-Read-Blocks> +
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
<Shared-Written-Blocks>N</Shared-Written-Blocks>+
<Local-Hit-Blocks>N</Local-Hit-Blocks> +
<Local-Read-Blocks>N</Local-Read-Blocks> +
<Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
<Local-Written-Blocks>N</Local-Written-Blocks> +
<Temp-Read-Blocks>N</Temp-Read-Blocks> +
<Temp-Written-Blocks>N</Temp-Written-Blocks> +
</Plan> +
<Planning> +
<Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
<Shared-Read-Blocks>N</Shared-Read-Blocks> +
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
<Shared-Written-Blocks>N</Shared-Written-Blocks>+
<Local-Hit-Blocks>N</Local-Hit-Blocks> +
<Local-Read-Blocks>N</Local-Read-Blocks> +
<Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
<Local-Written-Blocks>N</Local-Written-Blocks> +
<Temp-Read-Blocks>N</Temp-Read-Blocks> +
<Temp-Written-Blocks>N</Temp-Written-Blocks> +
</Planning> +
<Planning-Time>N.N</Planning-Time> +
<Triggers> +
</Triggers> +
<Execution-Time>N.N</Execution-Time> +
</Query> +
</explain>
(1 row)
select explain_filter('explain (analyze, serialize, buffers, format yaml) select * from int8_tbl i8');
explain_filter
-------------------------------
- Plan: +
Node Type: "Seq Scan" +
Parallel Aware: false +
Async Capable: false +
Relation Name: "int8_tbl"+
Alias: "i8" +
Startup Cost: N.N +
Total Cost: N.N +
Plan Rows: N +
Plan Width: N +
Actual Startup Time: N.N +
Actual Total Time: N.N +
Actual Rows: N.N +
Actual Loops: N +
Disabled: false +
Shared Hit Blocks: N +
Shared Read Blocks: N +
Shared Dirtied Blocks: N +
Shared Written Blocks: N +
Local Hit Blocks: N +
Local Read Blocks: N +
Local Dirtied Blocks: N +
Local Written Blocks: N +
Temp Read Blocks: N +
Temp Written Blocks: N +
Planning: +
Shared Hit Blocks: N +
Shared Read Blocks: N +
Shared Dirtied Blocks: N +
Shared Written Blocks: N +
Local Hit Blocks: N +
Local Read Blocks: N +
Local Dirtied Blocks: N +
Local Written Blocks: N +
Temp Read Blocks: N +
Temp Written Blocks: N +
Planning Time: N.N +
Triggers: +
Serialization: +
Time: N.N +
Output Volume: N +
Format: "text" +
Shared Hit Blocks: N +
Shared Read Blocks: N +
Shared Dirtied Blocks: N +
Shared Written Blocks: N +
Local Hit Blocks: N +
Local Read Blocks: N +
Local Dirtied Blocks: N +
Local Written Blocks: N +
Temp Read Blocks: N +
Temp Written Blocks: N +
Execution Time: N.N
(1 row)
select explain_filter('explain (buffers, format text) select * from int8_tbl i8');
explain_filter
---------------------------------------------------------
Seq Scan on int8_tbl i8 (cost=N.N..N.N rows=N width=N)
(1 row)
select explain_filter('explain (buffers, format json) select * from int8_tbl i8');
explain_filter
------------------------------------
[ +
{ +
"Plan": { +
"Node Type": "Seq Scan", +
"Parallel Aware": false, +
"Async Capable": false, +
"Relation Name": "int8_tbl",+
"Alias": "i8", +
"Startup Cost": N.N, +
"Total Cost": N.N, +
"Plan Rows": N, +
"Plan Width": N, +
"Disabled": false, +
"Shared Hit Blocks": N, +
"Shared Read Blocks": N, +
"Shared Dirtied Blocks": N, +
"Shared Written Blocks": N, +
"Local Hit Blocks": N, +
"Local Read Blocks": N, +
"Local Dirtied Blocks": N, +
"Local Written Blocks": N, +
"Temp Read Blocks": N, +
"Temp Written Blocks": N +
}, +
"Planning": { +
"Shared Hit Blocks": N, +
"Shared Read Blocks": N, +
"Shared Dirtied Blocks": N, +
"Shared Written Blocks": N, +
"Local Hit Blocks": N, +
"Local Read Blocks": N, +
"Local Dirtied Blocks": N, +
"Local Written Blocks": N, +
"Temp Read Blocks": N, +
"Temp Written Blocks": N +
} +
} +
]
\a
select explain_filter('explain (analyze, buffers, format xml) select * from int8_tbl i8');
explain_filter
<explain xmlns="http://www.postgresql.org/N/explain">
<Query>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parallel-Aware>false</Parallel-Aware>
<Async-Capable>false</Async-Capable>
<Relation-Name>int8_tbl</Relation-Name>
<Alias>i8</Alias>
<Startup-Cost>N.N</Startup-Cost>
<Total-Cost>N.N</Total-Cost>
<Plan-Rows>N</Plan-Rows>
<Plan-Width>N</Plan-Width>
<Actual-Startup-Time>N.N</Actual-Startup-Time>
<Actual-Total-Time>N.N</Actual-Total-Time>
<Actual-Rows>N.N</Actual-Rows>
<Actual-Loops>N</Actual-Loops>
<Disabled>false</Disabled>
<Shared-Hit-Blocks>N</Shared-Hit-Blocks>
<Shared-Read-Blocks>N</Shared-Read-Blocks>
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>
<Shared-Written-Blocks>N</Shared-Written-Blocks>
<Local-Hit-Blocks>N</Local-Hit-Blocks>
<Local-Read-Blocks>N</Local-Read-Blocks>
<Local-Dirtied-Blocks>N</Local-Dirtied-Blocks>
<Local-Written-Blocks>N</Local-Written-Blocks>
<Temp-Read-Blocks>N</Temp-Read-Blocks>
<Temp-Written-Blocks>N</Temp-Written-Blocks>
</Plan>
<Planning>
<Shared-Hit-Blocks>N</Shared-Hit-Blocks>
<Shared-Read-Blocks>N</Shared-Read-Blocks>
<Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>
<Shared-Written-Blocks>N</Shared-Written-Blocks>
<Local-Hit-Blocks>N</Local-Hit-Blocks>
<Local-Read-Blocks>N</Local-Read-Blocks>
<Local-Dirtied-Blocks>N</Local-Dirtied-Blocks>
<Local-Written-Blocks>N</Local-Written-Blocks>
<Temp-Read-Blocks>N</Temp-Read-Blocks>
<Temp-Written-Blocks>N</Temp-Written-Blocks>
</Planning>
<Planning-Time>N.N</Planning-Time>
<Triggers>
</Triggers>
<Execution-Time>N.N</Execution-Time>
</Query>
</explain>
(1 row)
select explain_filter('explain (analyze, serialize, buffers, format yaml) select * from int8_tbl i8');
explain_filter
- Plan:
Node Type: "Seq Scan"
Parallel Aware: false
Async Capable: false
Relation Name: "int8_tbl"
Alias: "i8"
Startup Cost: N.N
Total Cost: N.N
Plan Rows: N
Plan Width: N
Actual Startup Time: N.N
Actual Total Time: N.N
Actual Rows: N.N
Actual Loops: N
Disabled: false
Shared Hit Blocks: N
Shared Read Blocks: N
Shared Dirtied Blocks: N
Shared Written Blocks: N
Local Hit Blocks: N
Local Read Blocks: N
Local Dirtied Blocks: N
Local Written Blocks: N
Temp Read Blocks: N
Temp Written Blocks: N
Planning:
Shared Hit Blocks: N
Shared Read Blocks: N
Shared Dirtied Blocks: N
Shared Written Blocks: N
Local Hit Blocks: N
Local Read Blocks: N
Local Dirtied Blocks: N
Local Written Blocks: N
Temp Read Blocks: N
Temp Written Blocks: N
Planning Time: N.N
Triggers:
Serialization:
Time: N.N
Output Volume: N
Format: "text"
Shared Hit Blocks: N
Shared Read Blocks: N
Shared Dirtied Blocks: N
Shared Written Blocks: N
Local Hit Blocks: N
Local Read Blocks: N
Local Dirtied Blocks: N
Local Written Blocks: N
Temp Read Blocks: N
Temp Written Blocks: N
Execution Time: N.N
(1 row)
select explain_filter('explain (buffers, format json) select * from int8_tbl i8');
explain_filter
[
{
"Plan": {
"Node Type": "Seq Scan",
"Parallel Aware": false,
"Async Capable": false,
"Relation Name": "int8_tbl",
"Alias": "i8",
"Startup Cost": N.N,
"Total Cost": N.N,
"Plan Rows": N,
"Plan Width": N,
"Disabled": false,
"Shared Hit Blocks": N,
"Shared Read Blocks": N,
"Shared Dirtied Blocks": N,
"Shared Written Blocks": N,
"Local Hit Blocks": N,
"Local Read Blocks": N,
"Local Dirtied Blocks": N,
"Local Written Blocks": N,
"Temp Read Blocks": N,
"Temp Written Blocks": N
},
"Planning": {
"Shared Hit Blocks": N,
"Shared Read Blocks": N,
"Shared Dirtied Blocks": N,
"Shared Written Blocks": N,
"Local Hit Blocks": N,
"Local Read Blocks": N,
"Local Dirtied Blocks": N,
"Local Written Blocks": N,
"Temp Read Blocks": N,
"Temp Written Blocks": N
}
}
]
(1 row)
\a
-- Check expansion of window definitions
select explain_filter('explain verbose select sum(unique1) over w, sum(unique2) over (w order by hundred), sum(tenthous) over (w order by hundred) from tenk1 window w as (partition by ten)');
explain_filter

View file

@ -66,10 +66,13 @@ select explain_filter('explain select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers off) select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers off, verbose) select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers, format text) select * from int8_tbl i8');
select explain_filter('explain (buffers, format text) select * from int8_tbl i8');
\a
select explain_filter('explain (analyze, buffers, format xml) select * from int8_tbl i8');
select explain_filter('explain (analyze, serialize, buffers, format yaml) select * from int8_tbl i8');
select explain_filter('explain (buffers, format text) select * from int8_tbl i8');
select explain_filter('explain (buffers, format json) select * from int8_tbl i8');
\a
-- Check expansion of window definitions