|
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 | +staticinlinebool |
| 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 | +elseif (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 |
| -elseif (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 clauseis usable with these input rels. |
| 1010 | + * Check if clausehas 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 |
| -elseif (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 |
| -elseif (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 */
|
|