diff options
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinrels.c | 57 |
4 files changed, 54 insertions, 15 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index ba33da829a9..0b9c5819820 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -54,7 +54,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.200 2008/10/21 20:42:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.201 2008/11/22 22:47:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2481,7 +2481,7 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, break; case JOIN_SEMI: nrows = outer_rel->rows * jselec; - nrows *= pselec; + /* pselec not used */ break; case JOIN_ANTI: nrows = outer_rel->rows * (1.0 - jselec); diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 297c50389fb..5d1e3154923 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.233 2008/09/12 14:56:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.234 2008/11/22 22:47:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1647,10 +1647,10 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, switch (jointype) { case JOIN_INNER: + case JOIN_SEMI: isouterjoin = false; break; case JOIN_LEFT: - case JOIN_SEMI: case JOIN_ANTI: isouterjoin = true; break; diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index eaf0ffa4276..fe70df49ad4 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.118 2008/10/04 21:56:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.119 2008/11/22 22:47:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -744,12 +744,12 @@ hash_inner_and_outer(PlannerInfo *root, switch (jointype) { case JOIN_INNER: + case JOIN_SEMI: case JOIN_UNIQUE_OUTER: case JOIN_UNIQUE_INNER: isouterjoin = false; break; case JOIN_LEFT: - case JOIN_SEMI: case JOIN_ANTI: isouterjoin = true; break; diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 9ac0cc97431..5f49ee7e290 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.94 2008/08/17 19:40:11 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.95 2008/11/22 22:47:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -419,6 +419,27 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, match_sjinfo = sjinfo; reversed = true; } + else if (sjinfo->jointype == JOIN_SEMI && + bms_equal(sjinfo->syn_righthand, rel2->relids)) + { + /* + * For a semijoin, we can join the RHS to anything else by + * unique-ifying the RHS. + */ + if (match_sjinfo) + return false; /* invalid join path */ + match_sjinfo = sjinfo; + reversed = false; + } + else if (sjinfo->jointype == JOIN_SEMI && + bms_equal(sjinfo->syn_righthand, rel1->relids)) + { + /* Reversed semijoin case */ + if (match_sjinfo) + return false; /* invalid join path */ + match_sjinfo = sjinfo; + reversed = true; + } else { /*---------- @@ -444,14 +465,24 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, * We assume that make_outerjoininfo() set things up correctly * so that we'll only match to some SJ if the join is valid. * Set flag here to check at bottom of loop. + * + * For a semijoin, assume it's okay if either side fully contains + * the RHS (per the unique-ification case above). *---------- */ - if (bms_overlap(rel1->relids, sjinfo->min_righthand) && + if (sjinfo->jointype != JOIN_SEMI && + bms_overlap(rel1->relids, sjinfo->min_righthand) && bms_overlap(rel2->relids, sjinfo->min_righthand)) { /* seems OK */ Assert(!bms_overlap(joinrelids, sjinfo->min_lefthand)); } + else if (sjinfo->jointype == JOIN_SEMI && + (bms_is_subset(sjinfo->syn_righthand, rel1->relids) || + bms_is_subset(sjinfo->syn_righthand, rel2->relids))) + { + /* seems OK */ + } else is_valid_inner = false; } @@ -612,15 +643,23 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) restrictlist); break; case JOIN_SEMI: - if (is_dummy_rel(rel1) || is_dummy_rel(rel2) || - restriction_is_constant_false(restrictlist)) + /* + * Do these steps only if we actually have a regular semijoin, + * as opposed to a case where we should unique-ify the RHS. + */ + if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) && + bms_is_subset(sjinfo->min_righthand, rel2->relids)) { - mark_dummy_rel(joinrel); - break; + if (is_dummy_rel(rel1) || is_dummy_rel(rel2) || + restriction_is_constant_false(restrictlist)) + { + mark_dummy_rel(joinrel); + break; + } + add_paths_to_joinrel(root, joinrel, rel1, rel2, + JOIN_SEMI, sjinfo, + restrictlist); } - add_paths_to_joinrel(root, joinrel, rel1, rel2, - JOIN_SEMI, sjinfo, - restrictlist); /* * If we know how to unique-ify the RHS and one input rel is |