*
* Note: do this after join_is_removable(), because this sets the
* outer_is_left flags in the mergejoin clauses, while join_is_removable
- * uses those flags for its own purposes.
+ * uses those flags for its own purposes. Currently, they set the flags
+ * the same way anyway, but let's avoid unnecessary entanglement.
*/
if (enable_mergejoin || jointype == JOIN_FULL)
mergeclause_list = select_mergejoin_clauses(root,
restrictlist, jointype, sjinfo);
}
+/*
+ * clause_matches_join
+ * Determine whether a join clause is of the right form to use in this join.
+ *
+ * We already know that the clause is a binary opclause referencing only the
+ * rels in the current join. The point here is to check whether it has the
+ * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr",
+ * rather than mixing outer and inner vars on either side. If it is usable,
+ * we set the transient flag outer_is_left to identify which side is which.
+ */
+static inline bool
+clause_matches_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
+ RelOptInfo *innerrel)
+{
+ if (bms_is_subset(rinfo->left_relids, outerrel->relids) &&
+ bms_is_subset(rinfo->right_relids, innerrel->relids))
+ {
+ /* lefthand side is outer */
+ rinfo->outer_is_left = true;
+ return true;
+ }
+ else if (bms_is_subset(rinfo->left_relids, innerrel->relids) &&
+ bms_is_subset(rinfo->right_relids, outerrel->relids))
+ {
+ /* righthand side is outer */
+ rinfo->outer_is_left = false;
+ return true;
+ }
+ return false; /* no good for these input relations */
+}
+
/*
* join_is_removable
* Determine whether we need not perform the join at all, because
continue; /* not mergejoinable */
/*
- * Check if clause is usable with these input rels. All the vars
- * needed on each side of the clause must be available from one or the
- * other of the input rels.
+ * Check if clause has the form "outer op inner" or "inner op outer".
*/
- if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, innerrel->relids))
- {
- /* righthand side is inner */
- restrictinfo->outer_is_left = true;
- }
- else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, outerrel->relids))
- {
- /* lefthand side is inner */
- restrictinfo->outer_is_left = false;
- }
- else
+ if (!clause_matches_join(restrictinfo, outerrel, innerrel))
continue; /* no good for these input relations */
/* OK, add to list */
{
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
- if (!restrictinfo->can_join ||
- restrictinfo->hashjoinoperator == InvalidOid)
- continue; /* not hashjoinable */
-
/*
* If processing an outer join, only use its own join clauses for
* hashing. For inner joins we need not be so picky.
if (isouterjoin && restrictinfo->is_pushed_down)
continue;
+ if (!restrictinfo->can_join ||
+ restrictinfo->hashjoinoperator == InvalidOid)
+ continue; /* not hashjoinable */
+
/*
- * Check if clause is usable with these input rels.
+ * Check if clause has the form "outer op inner" or "inner op outer".
*/
- if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, innerrel->relids))
- {
- /* righthand side is inner */
- }
- else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, outerrel->relids))
- {
- /* lefthand side is inner */
- }
- else
+ if (!clause_matches_join(restrictinfo, outerrel, innerrel))
continue; /* no good for these input relations */
hashclauses = lappend(hashclauses, restrictinfo);
}
/*
- * Check if clause is usable with these input rels. All the vars
- * needed on each side of the clause must be available from one or the
- * other of the input rels.
+ * Check if clause has the form "outer op inner" or "inner op outer".
*/
- if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, innerrel->relids))
- {
- /* righthand side is inner */
- restrictinfo->outer_is_left = true;
- }
- else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) &&
- bms_is_subset(restrictinfo->right_relids, outerrel->relids))
- {
- /* lefthand side is inner */
- restrictinfo->outer_is_left = false;
- }
- else
+ if (!clause_matches_join(restrictinfo, outerrel, innerrel))
{
have_nonmergeable_joinclause = true;
continue; /* no good for these input relations */