From 7998e8ca6a7fb74968c64461263af5311b5e1074 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 8 Mar 2004 17:20:17 +0000 Subject: [PATCH] Test for whether a previous IN join restricts the current join was too strict, per discussion with Dennis Haney. Also, rearrange the preceding tests to avoid redundancy. --- src/backend/optimizer/path/joinrels.c | 52 ++++++++++++++++----------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 50b9aef0110..07caab48ac6 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.66 2004/01/24 00:37:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.67 2004/03/08 17:20:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -483,35 +483,45 @@ make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2, InClauseInfo *ininfo = (InClauseInfo *) lfirst(l); /* - * Cannot join if proposed join contains part, but only part, - * of the RHS, *and* it contains rels not in the RHS. + * This IN clause is not relevant unless its RHS overlaps the + * proposed join. (Check this first as a fast path for dismissing + * most irrelevant INs quickly.) */ - if (bms_overlap(ininfo->righthand, joinrelids) && - !bms_is_subset(ininfo->righthand, joinrelids) && - !bms_is_subset(joinrelids, ininfo->righthand)) + if (!bms_overlap(ininfo->righthand, joinrelids)) + continue; + + /* + * If we are still building the IN clause's RHS, then this IN + * clause isn't relevant yet. + */ + if (bms_is_subset(joinrelids, ininfo->righthand)) + continue; + + /* + * Cannot join if proposed join contains rels not in the RHS + * *and* contains only part of the RHS. We must build the + * complete RHS (subselect's join) before it can be joined to + * rels outside the subselect. + */ + if (!bms_is_subset(ininfo->righthand, joinrelids)) { bms_free(joinrelids); return NULL; } /* - * No issue unless we are looking at a join of the IN's RHS to - * other stuff. + * At this point we are considering a join of the IN's RHS to + * some other rel(s). + * + * If we already joined IN's RHS to any other rels in either + * input path, then this join is not constrained (the necessary + * work was done at the lower level where that join occurred). */ - if (!(bms_is_subset(ininfo->righthand, joinrelids) && - !bms_equal(ininfo->righthand, joinrelids))) + if (bms_is_subset(ininfo->righthand, rel1->relids) && + !bms_equal(ininfo->righthand, rel1->relids)) continue; - - /* - * If we already joined IN's RHS to any part of its LHS in - * either input path, then this join is not constrained (the - * necessary work was done at a lower level). - */ - if (bms_overlap(ininfo->lefthand, rel1->relids) && - bms_is_subset(ininfo->righthand, rel1->relids)) - continue; - if (bms_overlap(ininfo->lefthand, rel2->relids) && - bms_is_subset(ininfo->righthand, rel2->relids)) + if (bms_is_subset(ininfo->righthand, rel2->relids) && + !bms_equal(ininfo->righthand, rel2->relids)) continue; /*