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:
parent
d8221dfa6d
commit
4df8de7a68
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user