Skip to content

Commit e5b8aa6

Browse files
committed
Fix bogus handling of JOIN_UNIQUE_OUTER/INNER cases for parallel joins.
consider_parallel_nestloop passed the wrong jointype down to its subroutines for JOIN_UNIQUE_INNER cases (it should pass JOIN_INNER), and it thought that it could pass paths other than innerrel->cheapest_total_path to create_unique_path, which create_unique_path is not on board with. These bugs would lead to assertion failures or other errors, suggesting that this code path hasn't been tested much. hash_inner_and_outer's code for parallel join effectively treated both JOIN_UNIQUE_OUTER and JOIN_UNIQUE_INNER the same as JOIN_INNER (for different reasons :-(), leading to incorrect plans that treated a semijoin as if it were a plain join. Michael Day submitted a test case demonstrating that hash_inner_and_outer failed for JOIN_UNIQUE_OUTER, and I found the other cases through code review. Report: https://postgr.es/m/D0E8A029-D1AC-42E8-979A-5DE4A77E4413@rcmail.com
1 parent 0c65061 commit e5b8aa6

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

src/backend/optimizer/path/joinpath.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,8 +1217,12 @@ consider_parallel_nestloop(PlannerInfo *root,
12171217
JoinType jointype,
12181218
JoinPathExtraData *extra)
12191219
{
1220+
JoinType save_jointype = jointype;
12201221
ListCell *lc1;
12211222

1223+
if (jointype == JOIN_UNIQUE_INNER)
1224+
jointype = JOIN_INNER;
1225+
12221226
foreach(lc1, outerrel->partial_pathlist)
12231227
{
12241228
Path *outerpath = (Path *) lfirst(lc1);
@@ -1244,18 +1248,19 @@ consider_parallel_nestloop(PlannerInfo *root,
12441248
continue;
12451249

12461250
/*
1247-
* Like match_unsorted_outer, we only consider a single nestloop
1248-
* path when the jointype is JOIN_UNIQUE_INNER. But we have to
1249-
* scan cheapest_parameterized_paths to find the one we want to
1250-
* consider, because cheapest_total_path might not be
1251-
* parallel-safe.
1251+
* If we're doing JOIN_UNIQUE_INNER, we can only use the inner's
1252+
* cheapest_total_path, and we have to unique-ify it. (We might
1253+
* be able to relax this to allow other safe, unparameterized
1254+
* inner paths, but right now create_unique_path is not on board
1255+
* with that.)
12521256
*/
1253-
if (jointype == JOIN_UNIQUE_INNER)
1257+
if (save_jointype == JOIN_UNIQUE_INNER)
12541258
{
1255-
if (!bms_is_empty(PATH_REQ_OUTER(innerpath)))
1259+
if (innerpath != innerrel->cheapest_total_path)
12561260
continue;
12571261
innerpath = (Path *) create_unique_path(root, innerrel,
1258-
innerpath, extra->sjinfo);
1262+
innerpath,
1263+
extra->sjinfo);
12591264
Assert(innerpath);
12601265
}
12611266

@@ -1284,6 +1289,7 @@ hash_inner_and_outer(PlannerInfo *root,
12841289
JoinType jointype,
12851290
JoinPathExtraData *extra)
12861291
{
1292+
JoinType save_jointype = jointype;
12871293
bool isouterjoin = IS_OUTER_JOIN(jointype);
12881294
List *hashclauses;
12891295
ListCell *l;
@@ -1450,9 +1456,9 @@ hash_inner_and_outer(PlannerInfo *root,
14501456
* extended rows. Also, the resulting path must not be parameterized.
14511457
*/
14521458
if (joinrel->consider_parallel &&
1453-
jointype != JOIN_UNIQUE_OUTER &&
1454-
jointype != JOIN_FULL &&
1455-
jointype != JOIN_RIGHT &&
1459+
save_jointype != JOIN_UNIQUE_OUTER &&
1460+
save_jointype != JOIN_FULL &&
1461+
save_jointype != JOIN_RIGHT &&
14561462
outerrel->partial_pathlist != NIL &&
14571463
bms_is_empty(joinrel->lateral_relids))
14581464
{
@@ -1466,11 +1472,12 @@ hash_inner_and_outer(PlannerInfo *root,
14661472
* Normally, given that the joinrel is parallel-safe, the cheapest
14671473
* total inner path will also be parallel-safe, but if not, we'll
14681474
* have to search cheapest_parameterized_paths for the cheapest
1469-
* unparameterized inner path.
1475+
* safe, unparameterized inner path. If doing JOIN_UNIQUE_INNER,
1476+
* we can't use any alternative inner path.
14701477
*/
14711478
if (cheapest_total_inner->parallel_safe)
14721479
cheapest_safe_inner = cheapest_total_inner;
1473-
else
1480+
else if (save_jointype != JOIN_UNIQUE_INNER)
14741481
{
14751482
ListCell *lc;
14761483

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