|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.124 2009/09/17 20:49:28 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.125 2009/09/18 17:24:51 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -102,7 +102,8 @@ add_paths_to_joinrel(PlannerInfo *root,
|
102 | 102 | *
|
103 | 103 | * Note: do this after join_is_removable(), because this sets the
|
104 | 104 | * outer_is_left flags in the mergejoin clauses, while join_is_removable
|
105 |
| - * uses those flags for its own purposes. |
| 105 | + * uses those flags for its own purposes. Currently, they set the flags |
| 106 | + * the same way anyway, but let's avoid unnecessary entanglement. |
106 | 107 | */
|
107 | 108 | if (enable_mergejoin || jointype == JOIN_FULL)
|
108 | 109 | mergeclause_list = select_mergejoin_clauses(root,
|
@@ -153,6 +154,37 @@ add_paths_to_joinrel(PlannerInfo *root,
|
153 | 154 | restrictlist, jointype, sjinfo);
|
154 | 155 | }
|
155 | 156 |
|
| 157 | +/* |
| 158 | + * clause_matches_join |
| 159 | + * Determine whether a join clause is of the right form to use in this join. |
| 160 | + * |
| 161 | + * We already know that the clause is a binary opclause referencing only the |
| 162 | + * rels in the current join. The point here is to check whether it has the |
| 163 | + * form "outerrel_expr op innerrel_expr" or "innerrel_expr op outerrel_expr", |
| 164 | + * rather than mixing outer and inner vars on either side. If it is usable, |
| 165 | + * we set the transient flag outer_is_left to identify which side is which. |
| 166 | + */ |
| 167 | +static inline bool |
| 168 | +clause_matches_join(RestrictInfo *rinfo, RelOptInfo *outerrel, |
| 169 | + RelOptInfo *innerrel) |
| 170 | +{ |
| 171 | + if (bms_is_subset(rinfo->left_relids, outerrel->relids) && |
| 172 | + bms_is_subset(rinfo->right_relids, innerrel->relids)) |
| 173 | + { |
| 174 | + /* lefthand side is outer */ |
| 175 | + rinfo->outer_is_left = true; |
| 176 | + return true; |
| 177 | + } |
| 178 | + else if (bms_is_subset(rinfo->left_relids, innerrel->relids) && |
| 179 | + bms_is_subset(rinfo->right_relids, outerrel->relids)) |
| 180 | + { |
| 181 | + /* righthand side is outer */ |
| 182 | + rinfo->outer_is_left = false; |
| 183 | + return true; |
| 184 | + } |
| 185 | + return false; /* no good for these input relations */ |
| 186 | +} |
| 187 | + |
156 | 188 | /*
|
157 | 189 | * join_is_removable
|
158 | 190 | * Determine whether we need not perform the join at all, because
|
@@ -233,23 +265,9 @@ join_is_removable(PlannerInfo *root,
|
233 | 265 | continue; /* not mergejoinable */
|
234 | 266 |
|
235 | 267 | /*
|
236 |
| - * Check if clause is usable with these input rels. All the vars |
237 |
| - * needed on each side of the clause must be available from one or the |
238 |
| - * other of the input rels. |
| 268 | + * Check if clause has the form "outer op inner" or "inner op outer". |
239 | 269 | */
|
240 |
| - if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) && |
241 |
| - bms_is_subset(restrictinfo->right_relids, innerrel->relids)) |
242 |
| - { |
243 |
| - /* righthand side is inner */ |
244 |
| - restrictinfo->outer_is_left = true; |
245 |
| - } |
246 |
| - else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) && |
247 |
| - bms_is_subset(restrictinfo->right_relids, outerrel->relids)) |
248 |
| - { |
249 |
| - /* lefthand side is inner */ |
250 |
| - restrictinfo->outer_is_left = false; |
251 |
| - } |
252 |
| - else |
| 270 | + if (!clause_matches_join(restrictinfo, outerrel, innerrel)) |
253 | 271 | continue; /* no good for these input relations */
|
254 | 272 |
|
255 | 273 | /* OK, add to list */
|
@@ -977,31 +995,21 @@ hash_inner_and_outer(PlannerInfo *root,
|
977 | 995 | {
|
978 | 996 | RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
|
979 | 997 |
|
980 |
| - if (!restrictinfo->can_join || |
981 |
| - restrictinfo->hashjoinoperator == InvalidOid) |
982 |
| - continue; /* not hashjoinable */ |
983 |
| - |
984 | 998 | /*
|
985 | 999 | * If processing an outer join, only use its own join clauses for
|
986 | 1000 | * hashing. For inner joins we need not be so picky.
|
987 | 1001 | */
|
988 | 1002 | if (isouterjoin && restrictinfo->is_pushed_down)
|
989 | 1003 | continue;
|
990 | 1004 |
|
| 1005 | + if (!restrictinfo->can_join || |
| 1006 | + restrictinfo->hashjoinoperator == InvalidOid) |
| 1007 | + continue; /* not hashjoinable */ |
| 1008 | + |
991 | 1009 | /*
|
992 |
| - * Check if clause is usable with these input rels. |
| 1010 | + * Check if clause has the form "outer op inner" or "inner op outer". |
993 | 1011 | */
|
994 |
| - if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) && |
995 |
| - bms_is_subset(restrictinfo->right_relids, innerrel->relids)) |
996 |
| - { |
997 |
| - /* righthand side is inner */ |
998 |
| - } |
999 |
| - else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) && |
1000 |
| - bms_is_subset(restrictinfo->right_relids, outerrel->relids)) |
1001 |
| - { |
1002 |
| - /* lefthand side is inner */ |
1003 |
| - } |
1004 |
| - else |
| 1012 | + if (!clause_matches_join(restrictinfo, outerrel, innerrel)) |
1005 | 1013 | continue; /* no good for these input relations */
|
1006 | 1014 |
|
1007 | 1015 | hashclauses = lappend(hashclauses, restrictinfo);
|
@@ -1176,23 +1184,9 @@ select_mergejoin_clauses(PlannerInfo *root,
|
1176 | 1184 | }
|
1177 | 1185 |
|
1178 | 1186 | /*
|
1179 |
| - * Check if clause is usable with these input rels. All the vars |
1180 |
| - * needed on each side of the clause must be available from one or the |
1181 |
| - * other of the input rels. |
| 1187 | + * Check if clause has the form "outer op inner" or "inner op outer". |
1182 | 1188 | */
|
1183 |
| - if (bms_is_subset(restrictinfo->left_relids, outerrel->relids) && |
1184 |
| - bms_is_subset(restrictinfo->right_relids, innerrel->relids)) |
1185 |
| - { |
1186 |
| - /* righthand side is inner */ |
1187 |
| - restrictinfo->outer_is_left = true; |
1188 |
| - } |
1189 |
| - else if (bms_is_subset(restrictinfo->left_relids, innerrel->relids) && |
1190 |
| - bms_is_subset(restrictinfo->right_relids, outerrel->relids)) |
1191 |
| - { |
1192 |
| - /* lefthand side is inner */ |
1193 |
| - restrictinfo->outer_is_left = false; |
1194 |
| - } |
1195 |
| - else |
| 1189 | + if (!clause_matches_join(restrictinfo, outerrel, innerrel)) |
1196 | 1190 | {
|
1197 | 1191 | have_nonmergeable_joinclause = true;
|
1198 | 1192 | continue; /* no good for these input relations */
|
|
0 commit comments