Fix check for whether a clauseless join has to be forced in the presence of

outer joins.  Originally it was only looking for overlap of the righthand
side of a left join, but we have to do it on the lefthand side too.
Per example from Jean-Pierre Pelletier.
This commit is contained in:
Tom Lane 2006-10-24 17:50:22 +00:00
parent d8221dfa6d
commit 4df8de7a68
2 changed files with 25 additions and 11 deletions

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.80 2006/03/05 15:58:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.81 2006/10/24 17:50:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -262,23 +262,29 @@ desirable_join(PlannerInfo *root,
return true; return true;
/* /*
* Join if the rels are members of the same outer-join RHS. This is needed * Join if the rels are members of the same outer-join side. This is
* to improve the odds that we will find a valid solution in a case where * needed to ensure that we can find a valid solution in a case where
* an OJ RHS has a clauseless join. * an OJ contains a clauseless join.
*/ */
foreach(l, root->oj_info_list) foreach(l, root->oj_info_list)
{ {
OuterJoinInfo *ojinfo = (OuterJoinInfo *) lfirst(l); OuterJoinInfo *ojinfo = (OuterJoinInfo *) lfirst(l);
/* ignore full joins --- other mechanisms preserve their ordering */
if (ojinfo->is_full_join)
continue;
if (bms_is_subset(outer_rel->relids, ojinfo->min_righthand) && if (bms_is_subset(outer_rel->relids, ojinfo->min_righthand) &&
bms_is_subset(inner_rel->relids, ojinfo->min_righthand)) bms_is_subset(inner_rel->relids, ojinfo->min_righthand))
return true; return true;
if (bms_is_subset(outer_rel->relids, ojinfo->min_lefthand) &&
bms_is_subset(inner_rel->relids, ojinfo->min_lefthand))
return true;
} }
/* /*
* Join if the rels are members of the same IN sub-select. This is needed * Join if the rels are members of the same IN sub-select. This is needed
* to improve the odds that we will find a valid solution in a case where * to ensure that we can find a valid solution in a case where an IN
* an IN sub-select has a clauseless join. * sub-select has a clauseless join.
*/ */
foreach(l, root->in_info_list) foreach(l, root->in_info_list)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.80 2006/10/04 00:29:54 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.81 2006/10/24 17:50:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -87,9 +87,9 @@ make_rels_by_joins(PlannerInfo *root, int level, List **joinrels)
/* /*
* An exception occurs when there is a clauseless join inside a * An exception occurs when there is a clauseless join inside a
* construct that restricts join order, i.e., an outer join RHS or * construct that restricts join order, i.e., an outer join or
* an IN (sub-SELECT) construct. Here, the rel may well have join * an IN (sub-SELECT) construct. Here, the rel may well have join
* clauses against stuff outside the OJ RHS or IN sub-SELECT, but * clauses against stuff outside its OJ side or IN sub-SELECT, but
* the clauseless join *must* be done before we can make use of * the clauseless join *must* be done before we can make use of
* those join clauses. So do the clauseless join bit. * those join clauses. So do the clauseless join bit.
* *
@ -331,7 +331,7 @@ make_rels_by_clauseless_joins(PlannerInfo *root,
/* /*
* has_join_restriction * has_join_restriction
* Detect whether the specified relation has join-order restrictions * Detect whether the specified relation has join-order restrictions
* due to being inside an OJ RHS or an IN (sub-SELECT). * due to being inside an outer join or an IN (sub-SELECT).
*/ */
static bool static bool
has_join_restriction(PlannerInfo *root, RelOptInfo *rel) has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
@ -342,8 +342,16 @@ has_join_restriction(PlannerInfo *root, RelOptInfo *rel)
{ {
OuterJoinInfo *ojinfo = (OuterJoinInfo *) lfirst(l); OuterJoinInfo *ojinfo = (OuterJoinInfo *) lfirst(l);
/* ignore full joins --- other mechanisms preserve their ordering */
if (ojinfo->is_full_join)
continue;
/* anything inside the RHS is definitely restricted */
if (bms_is_subset(rel->relids, ojinfo->min_righthand)) if (bms_is_subset(rel->relids, ojinfo->min_righthand))
return true; return true;
/* if it's a proper subset of the LHS, it's also restricted */
if (bms_is_subset(rel->relids, ojinfo->min_lefthand) &&
!bms_equal(rel->relids, ojinfo->min_lefthand))
return true;
} }
foreach(l, root->in_info_list) foreach(l, root->in_info_list)