*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.91.4.2 2005/05/24 18:02:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.91.4.3 2005/10/25 20:30:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
List *result_list = NIL;
bool isouterjoin = IS_OUTER_JOIN(jointype);
+ bool have_nonmergeable_joinclause = false;
ListCell *l;
foreach(l, restrictlist)
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
/*
- * If processing an outer join, only use its own join clauses in
- * the merge. For inner joins we need not be so picky.
- *
- * Furthermore, if it is a right/full join then *all* the explicit
- * join clauses must be mergejoinable, else the executor will
- * fail. If we are asked for a right join then just return NIL to
- * indicate no mergejoin is possible (we can handle it as a left
- * join instead). If we are asked for a full join then emit an
- * error, because there is no fallback.
+ * If processing an outer join, only use its own join clauses in the
+ * merge. For inner joins we can use pushed-down clauses too.
+ * (Note: we don't set have_nonmergeable_joinclause here because
+ * pushed-down clauses will become otherquals not joinquals.)
*/
- if (isouterjoin)
- {
- if (restrictinfo->is_pushed_down)
- continue;
- switch (jointype)
- {
- case JOIN_RIGHT:
- if (!restrictinfo->can_join ||
- restrictinfo->mergejoinoperator == InvalidOid)
- return NIL; /* not mergejoinable */
- break;
- case JOIN_FULL:
- if (!restrictinfo->can_join ||
- restrictinfo->mergejoinoperator == InvalidOid)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
- break;
- default:
- /* otherwise, it's OK to have nonmergeable join quals */
- break;
- }
- }
+ if (isouterjoin && restrictinfo->is_pushed_down)
+ continue;
if (!restrictinfo->can_join ||
restrictinfo->mergejoinoperator == InvalidOid)
+ {
+ have_nonmergeable_joinclause = true;
continue; /* not mergejoinable */
+ }
/*
* Check if clause is usable with these input rels. All the vars
/* lefthand side is inner */
}
else
+ {
+ have_nonmergeable_joinclause = true;
continue; /* no good for these input relations */
+ }
result_list = lcons(restrictinfo, result_list);
}
+ /*
+ * If it is a right/full join then *all* the explicit join clauses must be
+ * mergejoinable, else the executor will fail. If we are asked for a right
+ * join then just return NIL to indicate no mergejoin is possible (we can
+ * handle it as a left join instead). If we are asked for a full join then
+ * emit an error, because there is no fallback.
+ */
+ if (have_nonmergeable_joinclause)
+ {
+ switch (jointype)
+ {
+ case JOIN_RIGHT:
+ return NIL; /* not mergejoinable */
+ case JOIN_FULL:
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
+ break;
+ default:
+ /* otherwise, it's OK to have nonmergeable join quals */
+ break;
+ }
+ }
+
return result_list;
}