Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+20-13
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)