|
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