* cdbpath_motion_for_join * * Decides where a join should be done. Adds Motion operators atop * the subpaths if needed to deliver their results to the join locus. * Returns the join locus if ok, or a null locus otherwise. If * jointype is JOIN_SEMI_DEDUP or JOIN_SEMI_DEDUP_REVERSE, this also * tacks a RowIdExpr on one side of the join, and *p_rowidexpr_id is * set to the ID of that. The ca
| 1359 | * It comes from select_mergejoin_clauses() in joinpath.c. |
| 1360 | */ |
| 1361 | CdbPathLocus |
| 1362 | cdbpath_motion_for_join(PlannerInfo *root, |
| 1363 | JoinType jointype, /* JOIN_INNER/FULL/LEFT/RIGHT/IN */ |
| 1364 | Path **p_outer_path, /* INOUT */ |
| 1365 | Path **p_inner_path, /* INOUT */ |
| 1366 | int *p_rowidexpr_id, /* OUT */ |
| 1367 | List *redistribution_clauses, /* equijoin RestrictInfo list */ |
| 1368 | List *restrict_clauses, |
| 1369 | List *outer_pathkeys, |
| 1370 | List *inner_pathkeys, |
| 1371 | bool outer_require_existing_order, |
| 1372 | bool inner_require_existing_order) |
| 1373 | { |
| 1374 | CdbpathMfjRel outer; |
| 1375 | CdbpathMfjRel inner; |
| 1376 | int numsegments; |
| 1377 | bool join_quals_contain_outer_references; |
| 1378 | ListCell *lc; |
| 1379 | |
| 1380 | *p_rowidexpr_id = 0; |
| 1381 | |
| 1382 | outer.pathkeys = outer_pathkeys; |
| 1383 | inner.pathkeys = inner_pathkeys; |
| 1384 | outer.path = *p_outer_path; |
| 1385 | inner.path = *p_inner_path; |
| 1386 | outer.locus = outer.path->locus; |
| 1387 | inner.locus = inner.path->locus; |
| 1388 | CdbPathLocus_MakeNull(&outer.move_to); |
| 1389 | CdbPathLocus_MakeNull(&inner.move_to); |
| 1390 | |
| 1391 | Assert(cdbpathlocus_is_valid(outer.locus)); |
| 1392 | Assert(cdbpathlocus_is_valid(inner.locus)); |
| 1393 | |
| 1394 | /* No parallel paths should get here. */ |
| 1395 | Assert(outer.locus.parallel_workers == 0); |
| 1396 | Assert(inner.locus.parallel_workers == 0); |
| 1397 | |
| 1398 | /* |
| 1399 | * Does the join quals contain references to outer query? If so, we must |
| 1400 | * evaluate them in the outer query's locus. That means pulling both |
| 1401 | * inputs to outer locus, and performing the join there. |
| 1402 | * |
| 1403 | * XXX: If there are pseudoconstant quals, they will be executed by a |
| 1404 | * gating Result with a One-Time Filter. In that case, the join's inputs |
| 1405 | * wouldn't need to be brought to the outer locus. We could execute the |
| 1406 | * join normally, and bring the result to the outer locus and put the |
| 1407 | * gating Result above the Motion, instead. But for now, we're not smart |
| 1408 | * like that. |
| 1409 | */ |
| 1410 | join_quals_contain_outer_references = false; |
| 1411 | foreach(lc, restrict_clauses) |
| 1412 | { |
| 1413 | RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); |
| 1414 | |
| 1415 | if (rinfo->contain_outer_query_references) |
| 1416 | { |
| 1417 | join_quals_contain_outer_references = true; |
| 1418 | break; |
no test coverage detected