* select_mergejoin_clauses * Select mergejoin clauses that are usable for a particular join. * Returns a list of RestrictInfo nodes for those clauses. * * *mergejoin_allowed is normally set to true, but it is set to false if * this is a right/full join and there are nonmergejoinable join clauses. * The executor's mergejoin machinery cannot handle such cases, so we have * to avoid genera
| 2403 | * currently of interest. |
| 2404 | */ |
| 2405 | static List * |
| 2406 | select_mergejoin_clauses(PlannerInfo *root, |
| 2407 | RelOptInfo *joinrel, |
| 2408 | RelOptInfo *outerrel, |
| 2409 | RelOptInfo *innerrel, |
| 2410 | List *restrictlist, |
| 2411 | JoinType jointype, |
| 2412 | bool *mergejoin_allowed) |
| 2413 | { |
| 2414 | List *result_list = NIL; |
| 2415 | bool isouterjoin = IS_OUTER_JOIN(jointype); |
| 2416 | bool have_nonmergeable_joinclause = false; |
| 2417 | ListCell *l; |
| 2418 | |
| 2419 | foreach(l, restrictlist) |
| 2420 | { |
| 2421 | RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l); |
| 2422 | |
| 2423 | /* |
| 2424 | * If processing an outer join, only use its own join clauses in the |
| 2425 | * merge. For inner joins we can use pushed-down clauses too. (Note: |
| 2426 | * we don't set have_nonmergeable_joinclause here because pushed-down |
| 2427 | * clauses will become otherquals not joinquals.) |
| 2428 | */ |
| 2429 | if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids)) |
| 2430 | continue; |
| 2431 | |
| 2432 | /* Check that clause is a mergeable operator clause */ |
| 2433 | if (!restrictinfo->can_join || |
| 2434 | restrictinfo->mergeopfamilies == NIL) |
| 2435 | { |
| 2436 | /* |
| 2437 | * The executor can handle extra joinquals that are constants, but |
| 2438 | * not anything else, when doing right/full merge join. (The |
| 2439 | * reason to support constants is so we can do FULL JOIN ON |
| 2440 | * FALSE.) |
| 2441 | */ |
| 2442 | if (!restrictinfo->clause || !IsA(restrictinfo->clause, Const)) |
| 2443 | have_nonmergeable_joinclause = true; |
| 2444 | continue; /* not mergejoinable */ |
| 2445 | } |
| 2446 | |
| 2447 | if (!OidIsValid(get_commutator(((OpExpr *)(restrictinfo->clause))->opno))) |
| 2448 | continue; |
| 2449 | |
| 2450 | /* |
| 2451 | * Check if clause has the form "outer op inner" or "inner op outer". |
| 2452 | */ |
| 2453 | if (!clause_sides_match_join(restrictinfo, outerrel, innerrel)) |
| 2454 | { |
| 2455 | have_nonmergeable_joinclause = true; |
| 2456 | continue; /* no good for these input relations */ |
| 2457 | } |
| 2458 | |
| 2459 | /* |
| 2460 | * Insist that each side have a non-redundant eclass. This |
| 2461 | * restriction is needed because various bits of the planner expect |
| 2462 | * that each clause in a merge be associable with some pathkey in a |
no test coverage detected