|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.84 2007/01/20 20:45:39 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.85 2007/02/13 02:31:03 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -350,8 +350,9 @@ has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
|
350 | 350 | /* ignore full joins --- other mechanisms preserve their ordering */
|
351 | 351 | if (ojinfo->is_full_join)
|
352 | 352 | continue;
|
353 |
| - /* anything inside the RHS is definitely restricted */ |
354 |
| - if (bms_is_subset(rel->relids, ojinfo->min_righthand)) |
| 353 | + /* if it overlaps RHS and isn't yet joined to LHS, it's restricted */ |
| 354 | + if (bms_overlap(rel->relids, ojinfo->min_righthand) && |
| 355 | + !bms_overlap(rel->relids, ojinfo->min_lefthand)) |
355 | 356 | return true;
|
356 | 357 | /* if it's a proper subset of the LHS, it's also restricted */
|
357 | 358 | if (bms_is_subset(rel->relids, ojinfo->min_lefthand) &&
|
@@ -468,16 +469,36 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
|
468 | 469 | /*----------
|
469 | 470 | * Otherwise, the proposed join overlaps the RHS but isn't
|
470 | 471 | * a valid implementation of this OJ. It might still be
|
471 |
| - * a valid implementation of some other OJ, however. We have |
472 |
| - * to allow this to support the associative identity |
473 |
| - * (a LJ b on Pab) LJ c ON Pbc = a LJ (b LJ c ON Pbc) on Pab |
| 472 | + * a legal join, however. If both inputs overlap the RHS, |
| 473 | + * assume that it's OK. Since the inputs presumably got past |
| 474 | + * this function's checks previously, they can't overlap the |
| 475 | + * LHS and their violations of the RHS boundary must represent |
| 476 | + * OJs that have been determined to commute with this one. |
| 477 | + * We have to allow this to work correctly in cases like |
| 478 | + * (a LEFT JOIN (b JOIN (c LEFT JOIN d))) |
| 479 | + * when the c/d join has been determined to commute with the join |
| 480 | + * to a, and hence d is not part of min_righthand for the upper |
| 481 | + * join. It should be legal to join b to c/d but this will appear |
| 482 | + * as a violation of the upper join's RHS. |
| 483 | + * Furthermore, if one input overlaps the RHS and the other does |
| 484 | + * not, we should still allow the join if it is a valid |
| 485 | + * implementation of some other OJ. We have to allow this to |
| 486 | + * support the associative identity |
| 487 | + * (a LJ b on Pab) LJ c ON Pbc = a LJ (b LJ c ON Pbc) on Pab |
474 | 488 | * since joining B directly to C violates the lower OJ's RHS.
|
475 | 489 | * We assume that make_outerjoininfo() set things up correctly
|
476 |
| - * so that we'll only match to the upper OJ if the transformation |
477 |
| - * is valid. Set flag here to check at bottom of loop. |
| 490 | + * so that we'll only match to some OJ if the join is valid. |
| 491 | + * Set flag here to check at bottom of loop. |
478 | 492 | *----------
|
479 | 493 | */
|
480 |
| - is_valid_inner = false; |
| 494 | + if (bms_overlap(rel1->relids, ojinfo->min_righthand) && |
| 495 | + bms_overlap(rel2->relids, ojinfo->min_righthand)) |
| 496 | + { |
| 497 | + /* seems OK */ |
| 498 | + Assert(!bms_overlap(joinrelids, ojinfo->min_lefthand)); |
| 499 | + } |
| 500 | + else |
| 501 | + is_valid_inner = false; |
481 | 502 | }
|
482 | 503 | }
|
483 | 504 |
|
|
0 commit comments