Skip to content

Commit 2ccd8fb

Browse files
committed
Consider parallel awareness when removing single-child Appends
8edd0e7 added some code to remove Append and MergeAppend nodes when they contained a single child node. As it turned out, this was unsafe to do when the Append/MergeAppend was parallel_aware and the child node was not. Removing the Append/MergeAppend, in this case, could lead to the child plan being called multiple times by parallel workers when it was unsafe to do so. Here we fix this by just not removing the Append/MergeAppend when the parallel_aware flag of the parent and child node don't match. Reported-by: Yura Sokolov Bug: #17335 Discussion: https://postgr.es/m/b59605fecb20ba9ea94e70ab60098c237c870628.camel%40postgrespro.ru Backpatch-through: 12, where 8edd0e7 was first introduced
1 parent fcc4340 commit 2ccd8fb

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,8 +1350,16 @@ set_append_references(PlannerInfo *root,
13501350
lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
13511351
}
13521352

1353-
/* Now, if there's just one, forget the Append and return that child */
1354-
if (list_length(aplan->appendplans) == 1)
1353+
/*
1354+
* See if it's safe to get rid of the Append entirely. For this to be
1355+
* safe, there must be only one child plan and that child plan's parallel
1356+
* awareness must match that of the Append's. The reason for the latter
1357+
* is that the if the Append is parallel aware and the child is not then
1358+
* the calling plan may execute the non-parallel aware child multiple
1359+
* times.
1360+
*/
1361+
if (list_length(aplan->appendplans) == 1 &&
1362+
((Plan *) linitial(aplan->appendplans))->parallel_aware == aplan->plan.parallel_aware)
13551363
return clean_up_removed_plan_level((Plan *) aplan,
13561364
(Plan *) linitial(aplan->appendplans));
13571365

@@ -1412,8 +1420,16 @@ set_mergeappend_references(PlannerInfo *root,
14121420
lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
14131421
}
14141422

1415-
/* Now, if there's just one, forget the MergeAppend and return that child */
1416-
if (list_length(mplan->mergeplans) == 1)
1423+
/*
1424+
* See if it's safe to get rid of the MergeAppend entirely. For this to
1425+
* be safe, there must be only one child plan and that child plan's
1426+
* parallel awareness must match that of the MergeAppend's. The reason
1427+
* for the latter is that the if the MergeAppend is parallel aware and the
1428+
* child is not then the calling plan may execute the non-parallel aware
1429+
* child multiple times.
1430+
*/
1431+
if (list_length(mplan->mergeplans) == 1 &&
1432+
((Plan *) linitial(mplan->mergeplans))->parallel_aware == mplan->plan.parallel_aware)
14171433
return clean_up_removed_plan_level((Plan *) mplan,
14181434
(Plan *) linitial(mplan->mergeplans));
14191435

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy