Skip to content

Commit ddb4015

Browse files
committed
Fix longstanding bug that would sometimes let the planner generate a bad plan
for an outer join; symptom is bogus error "RIGHT JOIN is only supported with merge-joinable join conditions". Problem was that select_mergejoin_clauses did its tests in the wrong order. We need to force left join not right join for a merge join when there are non-mergeable join clauses; but the test for this only accounted for mergejoinability of the clause operator, and not whether the left and right Vars were of the proper relations. Per report from Jean-Pierre Pelletier.
1 parent 62cfa0f commit ddb4015

File tree

1 file changed

+37
-32
lines changed

1 file changed

+37
-32
lines changed

src/backend/optimizer/path/joinpath.c

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.96 2005/10/15 02:49:20 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.97 2005/10/25 20:30:30 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -795,6 +795,7 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
795795
{
796796
List *result_list = NIL;
797797
bool isouterjoin = IS_OUTER_JOIN(jointype);
798+
bool have_nonmergeable_joinclause = false;
798799
ListCell *l;
799800

800801
foreach(l, restrictlist)
@@ -803,42 +804,19 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
803804

804805
/*
805806
* If processing an outer join, only use its own join clauses in the
806-
* merge. For inner joins we need not be so picky.
807-
*
808-
* Furthermore, if it is a right/full join then *all* the explicit join
809-
* clauses must be mergejoinable, else the executor will fail. If we
810-
* are asked for a right join then just return NIL to indicate no
811-
* mergejoin is possible (we can handle it as a left join instead). If
812-
* we are asked for a full join then emit an error, because there is
813-
* no fallback.
807+
* merge. For inner joins we can use pushed-down clauses too.
808+
* (Note: we don't set have_nonmergeable_joinclause here because
809+
* pushed-down clauses will become otherquals not joinquals.)
814810
*/
815-
if (isouterjoin)
816-
{
817-
if (restrictinfo->is_pushed_down)
818-
continue;
819-
switch (jointype)
820-
{
821-
case JOIN_RIGHT:
822-
if (!restrictinfo->can_join ||
823-
restrictinfo->mergejoinoperator == InvalidOid)
824-
return NIL; /* not mergejoinable */
825-
break;
826-
case JOIN_FULL:
827-
if (!restrictinfo->can_join ||
828-
restrictinfo->mergejoinoperator == InvalidOid)
829-
ereport(ERROR,
830-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
831-
errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
832-
break;
833-
default:
834-
/* otherwise, it's OK to have nonmergeable join quals */
835-
break;
836-
}
837-
}
811+
if (isouterjoin && restrictinfo->is_pushed_down)
812+
continue;
838813

839814
if (!restrictinfo->can_join ||
840815
restrictinfo->mergejoinoperator == InvalidOid)
816+
{
817+
have_nonmergeable_joinclause = true;
841818
continue; /* not mergejoinable */
819+
}
842820

843821
/*
844822
* Check if clause is usable with these input rels. All the vars
@@ -856,10 +834,37 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
856834
/* lefthand side is inner */
857835
}
858836
else
837+
{
838+
have_nonmergeable_joinclause = true;
859839
continue; /* no good for these input relations */
840+
}
860841

861842
result_list = lcons(restrictinfo, result_list);
862843
}
863844

845+
/*
846+
* If it is a right/full join then *all* the explicit join clauses must be
847+
* mergejoinable, else the executor will fail. If we are asked for a right
848+
* join then just return NIL to indicate no mergejoin is possible (we can
849+
* handle it as a left join instead). If we are asked for a full join then
850+
* emit an error, because there is no fallback.
851+
*/
852+
if (have_nonmergeable_joinclause)
853+
{
854+
switch (jointype)
855+
{
856+
case JOIN_RIGHT:
857+
return NIL; /* not mergejoinable */
858+
case JOIN_FULL:
859+
ereport(ERROR,
860+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
861+
errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
862+
break;
863+
default:
864+
/* otherwise, it's OK to have nonmergeable join quals */
865+
break;
866+
}
867+
}
868+
864869
return result_list;
865870
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy