Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7d91b60

Browse files
committed
Fix handling of "Subplans Removed" field in EXPLAIN output.
Commit 499be01 added this field in a rather poorly-thought-through manner, with the result being that rather than being a field of the Append or MergeAppend plan node as intended (and as it seems to be, in text format), it was actually an element of the "Plans" subgroup. At least in JSON format, that's flat out invalid syntax, because "Plans" is an array not an object. While it's not hard to move the generation of the field so that it appears where it's supposed to, this does result in a visible change in field order in text format, in cases where a Append or MergeAppend plan node has any InitPlans attached. That's slightly annoying to do in stable branches; but the alternative of continuing to emit broken non-text formats seems worse. Also, since the set of fields emitted is not supposed to be data-dependent in non-text formats, make sure that "Subplans Removed" appears in Append and MergeAppend nodes even when it's zero, in those formats. (The previous coding made it look like it could appear in some other node types such as BitmapAnd, but we don't actually support runtime pruning there, so don't emit it in those cases.) Per bug #16171 from Mahadevan Ramachandran. Fix by Daniel Gustafsson and Tom Lane, reviewed by Hamid Akhtar. Back-patch to v11 where this code came in. Discussion: https://postgr.es/m/16171-b72259ab75505fa2@postgresql.org
1 parent 177be9e commit 7d91b60

File tree

2 files changed

+50
-29
lines changed

2 files changed

+50
-29
lines changed

src/backend/commands/explain.c

+44-23
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,9 @@ static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es);
119119
static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es);
120120
static void show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
121121
ExplainState *es);
122-
static void ExplainMemberNodes(PlanState **planstates, int nsubnodes,
123-
int nplans, List *ancestors, ExplainState *es);
122+
static void ExplainMemberNodes(PlanState **planstates, int nplans,
123+
List *ancestors, ExplainState *es);
124+
static void ExplainMissingMembers(int nplans, int nchildren, ExplainState *es);
124125
static void ExplainSubPlans(List *plans, List *ancestors,
125126
const char *relationship, ExplainState *es);
126127
static void ExplainCustomChildren(CustomScanState *css,
@@ -1967,6 +1968,30 @@ ExplainNode(PlanState *planstate, List *ancestors,
19671968
ExplainFlushWorkersState(es);
19681969
es->workers_state = save_workers_state;
19691970

1971+
/*
1972+
* If partition pruning was done during executor initialization, the
1973+
* number of child plans we'll display below will be less than the number
1974+
* of subplans that was specified in the plan. To make this a bit less
1975+
* mysterious, emit an indication that this happened. Note that this
1976+
* field is emitted now because we want it to be a property of the parent
1977+
* node; it *cannot* be emitted within the Plans sub-node we'll open next.
1978+
*/
1979+
switch (nodeTag(plan))
1980+
{
1981+
case T_Append:
1982+
ExplainMissingMembers(((AppendState *) planstate)->as_nplans,
1983+
list_length(((Append *) plan)->appendplans),
1984+
es);
1985+
break;
1986+
case T_MergeAppend:
1987+
ExplainMissingMembers(((MergeAppendState *) planstate)->ms_nplans,
1988+
list_length(((MergeAppend *) plan)->mergeplans),
1989+
es);
1990+
break;
1991+
default:
1992+
break;
1993+
}
1994+
19701995
/* Get ready to display the child plans */
19711996
haschildren = planstate->initPlan ||
19721997
outerPlanState(planstate) ||
@@ -2007,31 +2032,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
20072032
case T_ModifyTable:
20082033
ExplainMemberNodes(((ModifyTableState *) planstate)->mt_plans,
20092034
((ModifyTableState *) planstate)->mt_nplans,
2010-
list_length(((ModifyTable *) plan)->plans),
20112035
ancestors, es);
20122036
break;
20132037
case T_Append:
20142038
ExplainMemberNodes(((AppendState *) planstate)->appendplans,
20152039
((AppendState *) planstate)->as_nplans,
2016-
list_length(((Append *) plan)->appendplans),
20172040
ancestors, es);
20182041
break;
20192042
case T_MergeAppend:
20202043
ExplainMemberNodes(((MergeAppendState *) planstate)->mergeplans,
20212044
((MergeAppendState *) planstate)->ms_nplans,
2022-
list_length(((MergeAppend *) plan)->mergeplans),
20232045
ancestors, es);
20242046
break;
20252047
case T_BitmapAnd:
20262048
ExplainMemberNodes(((BitmapAndState *) planstate)->bitmapplans,
20272049
((BitmapAndState *) planstate)->nplans,
2028-
list_length(((BitmapAnd *) plan)->bitmapplans),
20292050
ancestors, es);
20302051
break;
20312052
case T_BitmapOr:
20322053
ExplainMemberNodes(((BitmapOrState *) planstate)->bitmapplans,
20332054
((BitmapOrState *) planstate)->nplans,
2034-
list_length(((BitmapOr *) plan)->bitmapplans),
20352055
ancestors, es);
20362056
break;
20372057
case T_SubqueryScan:
@@ -3348,32 +3368,33 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
33483368
*
33493369
* The ancestors list should already contain the immediate parent of these
33503370
* plans.
3351-
*
3352-
* nsubnodes indicates the number of items in the planstates array.
3353-
* nplans indicates the original number of subnodes in the Plan, some of these
3354-
* may have been pruned by the run-time pruning code.
33553371
*/
33563372
static void
3357-
ExplainMemberNodes(PlanState **planstates, int nsubnodes, int nplans,
3373+
ExplainMemberNodes(PlanState **planstates, int nplans,
33583374
List *ancestors, ExplainState *es)
33593375
{
33603376
int j;
33613377

3362-
/*
3363-
* The number of subnodes being lower than the number of subplans that was
3364-
* specified in the plan means that some subnodes have been ignored per
3365-
* instruction for the partition pruning code during the executor
3366-
* initialization. To make this a bit less mysterious, we'll indicate
3367-
* here that this has happened.
3368-
*/
3369-
if (nsubnodes < nplans)
3370-
ExplainPropertyInteger("Subplans Removed", NULL, nplans - nsubnodes, es);
3371-
3372-
for (j = 0; j < nsubnodes; j++)
3378+
for (j = 0; j < nplans; j++)
33733379
ExplainNode(planstates[j], ancestors,
33743380
"Member", NULL, es);
33753381
}
33763382

3383+
/*
3384+
* Report about any pruned subnodes of an Append or MergeAppend node.
3385+
*
3386+
* nplans indicates the number of live subplans.
3387+
* nchildren indicates the original number of subnodes in the Plan;
3388+
* some of these may have been pruned by the run-time pruning code.
3389+
*/
3390+
static void
3391+
ExplainMissingMembers(int nplans, int nchildren, ExplainState *es)
3392+
{
3393+
if (nplans < nchildren || es->format != EXPLAIN_FORMAT_TEXT)
3394+
ExplainPropertyInteger("Subplans Removed", NULL,
3395+
nchildren - nplans, es);
3396+
}
3397+
33773398
/*
33783399
* Explain a list of SubPlans (or initPlans, which also use SubPlan nodes).
33793400
*

src/test/regress/expected/partition_prune.out

+6-6
Original file line numberDiff line numberDiff line change
@@ -1808,9 +1808,9 @@ explain (analyze, costs off, summary off, timing off) execute ab_q2 (2, 2);
18081808
QUERY PLAN
18091809
---------------------------------------------------------
18101810
Append (actual rows=0 loops=1)
1811+
Subplans Removed: 6
18111812
InitPlan 1 (returns $0)
18121813
-> Result (actual rows=1 loops=1)
1813-
Subplans Removed: 6
18141814
-> Seq Scan on ab_a2_b1 ab_1 (actual rows=0 loops=1)
18151815
Filter: ((a >= $1) AND (a <= $2) AND (b < $0))
18161816
-> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1)
@@ -1826,9 +1826,9 @@ explain (analyze, costs off, summary off, timing off) execute ab_q3 (2, 2);
18261826
QUERY PLAN
18271827
---------------------------------------------------------
18281828
Append (actual rows=0 loops=1)
1829+
Subplans Removed: 6
18291830
InitPlan 1 (returns $0)
18301831
-> Result (actual rows=1 loops=1)
1831-
Subplans Removed: 6
18321832
-> Seq Scan on ab_a1_b2 ab_1 (actual rows=0 loops=1)
18331833
Filter: ((b >= $1) AND (b <= $2) AND (a < $0))
18341834
-> Seq Scan on ab_a2_b2 ab_2 (actual rows=0 loops=1)
@@ -2396,9 +2396,9 @@ explain (analyze, costs off, summary off, timing off) execute ab_q6(1);
23962396
QUERY PLAN
23972397
--------------------------------------------------
23982398
Append (actual rows=0 loops=1)
2399+
Subplans Removed: 12
23992400
InitPlan 1 (returns $0)
24002401
-> Result (actual rows=1 loops=1)
2401-
Subplans Removed: 12
24022402
-> Seq Scan on ab_a1_b1 ab_1 (never executed)
24032403
Filter: ((a = $1) AND (b = $0))
24042404
-> Seq Scan on ab_a1_b2 ab_2 (never executed)
@@ -3032,9 +3032,9 @@ execute ps1(1);
30323032
QUERY PLAN
30333033
--------------------------------------------------------
30343034
Append (actual rows=1 loops=1)
3035+
Subplans Removed: 2
30353036
InitPlan 1 (returns $0)
30363037
-> Result (actual rows=1 loops=1)
3037-
Subplans Removed: 2
30383038
-> Seq Scan on mc3p1 mc3p_1 (actual rows=1 loops=1)
30393039
Filter: ((a = $1) AND (abs(b) < $0))
30403040
(6 rows)
@@ -3047,9 +3047,9 @@ execute ps2(1);
30473047
QUERY PLAN
30483048
--------------------------------------------------------
30493049
Append (actual rows=2 loops=1)
3050+
Subplans Removed: 1
30503051
InitPlan 1 (returns $0)
30513052
-> Result (actual rows=1 loops=1)
3052-
Subplans Removed: 1
30533053
-> Seq Scan on mc3p0 mc3p_1 (actual rows=1 loops=1)
30543054
Filter: ((a <= $1) AND (abs(b) < $0))
30553055
-> Seq Scan on mc3p1 mc3p_2 (actual rows=1 loops=1)
@@ -3594,9 +3594,9 @@ explain (costs off) execute q (1, 1);
35943594
QUERY PLAN
35953595
---------------------------------------------------------------
35963596
Append
3597+
Subplans Removed: 1
35973598
InitPlan 1 (returns $0)
35983599
-> Result
3599-
Subplans Removed: 1
36003600
-> Seq Scan on p1 p
36013601
Filter: ((a = $1) AND (b = $2) AND (c = $0))
36023602
-> Seq Scan on q111 q1

0 commit comments

Comments
 (0)