|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.131 2010/03/22 13:57:15 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.132 2010/03/28 22:59:32 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
22 | 22 | #include"optimizer/paths.h"
|
23 | 23 |
|
24 | 24 |
|
25 |
| -staticbooljoin_is_removable(PlannerInfo*root,RelOptInfo*joinrel, |
26 |
| -RelOptInfo*outerrel,RelOptInfo*innerrel, |
27 |
| -List*restrictlist,JoinTypejointype); |
28 |
| -staticvoidgenerate_outer_only(PlannerInfo*root,RelOptInfo*joinrel, |
29 |
| -RelOptInfo*outerrel); |
30 | 25 | staticvoidsort_inner_and_outer(PlannerInfo*root,RelOptInfo*joinrel,
|
31 | 26 | RelOptInfo*outerrel,RelOptInfo*innerrel,
|
32 | 27 | List*restrictlist,List*mergeclause_list,
|
@@ -83,27 +78,11 @@ add_paths_to_joinrel(PlannerInfo *root,
|
83 | 78 | {
|
84 | 79 | List*mergeclause_list=NIL;
|
85 | 80 |
|
86 |
| -/* |
87 |
| - * 0. Consider join removal. This is always the most efficient strategy, |
88 |
| - * so if it works, there's no need to consider anything further. |
89 |
| - */ |
90 |
| -if (join_is_removable(root,joinrel,outerrel,innerrel, |
91 |
| -restrictlist,jointype)) |
92 |
| -{ |
93 |
| -generate_outer_only(root,joinrel,outerrel); |
94 |
| -return; |
95 |
| -} |
96 |
| - |
97 | 81 | /*
|
98 | 82 | * Find potential mergejoin clauses. We can skip this if we are not
|
99 | 83 | * interested in doing a mergejoin. However, mergejoin is currently our
|
100 | 84 | * only way of implementing full outer joins, so override mergejoin
|
101 | 85 | * disable if it's a full join.
|
102 |
| - * |
103 |
| - * Note: do this after join_is_removable(), because this sets the |
104 |
| - * outer_is_left flags in the mergejoin clauses, while join_is_removable |
105 |
| - * uses those flags for its own purposes. Currently, they set the flags |
106 |
| - * the same way anyway, but let's avoid unnecessary entanglement. |
107 | 86 | */
|
108 | 87 | if (enable_mergejoin||jointype==JOIN_FULL)
|
109 | 88 | mergeclause_list=select_mergejoin_clauses(root,
|
@@ -185,188 +164,6 @@ clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel,
|
185 | 164 | return false;/* no good for these input relations */
|
186 | 165 | }
|
187 | 166 |
|
188 |
| -/* |
189 |
| - * join_is_removable |
190 |
| - * Determine whether we need not perform the join at all, because |
191 |
| - * it will just duplicate its left input. |
192 |
| - * |
193 |
| - * This is true for a left join for which the join condition cannot match |
194 |
| - * more than one inner-side row. (There are other possibly interesting |
195 |
| - * cases, but we don't have the infrastructure to prove them.) We also |
196 |
| - * have to check that the inner side doesn't generate any variables needed |
197 |
| - * above the join. |
198 |
| - * |
199 |
| - * Note: there is no need to consider the symmetrical case of duplicating the |
200 |
| - * right input, because add_paths_to_joinrel() will be called with each rel |
201 |
| - * on the outer side. |
202 |
| - */ |
203 |
| -staticbool |
204 |
| -join_is_removable(PlannerInfo*root, |
205 |
| -RelOptInfo*joinrel, |
206 |
| -RelOptInfo*outerrel, |
207 |
| -RelOptInfo*innerrel, |
208 |
| -List*restrictlist, |
209 |
| -JoinTypejointype) |
210 |
| -{ |
211 |
| -List*clause_list=NIL; |
212 |
| -ListCell*l; |
213 |
| -intattroff; |
214 |
| - |
215 |
| -/* |
216 |
| - * Currently, we only know how to remove left joins to a baserel with |
217 |
| - * unique indexes.We can check most of these criteria pretty trivially |
218 |
| - * to avoid doing useless extra work. But checking whether any of the |
219 |
| - * indexes are unique would require iterating over the indexlist, so for |
220 |
| - * now we just make sure there are indexes of some sort or other. If none |
221 |
| - * of them are unique, join removal will still fail, just slightly later. |
222 |
| - */ |
223 |
| -if (jointype!=JOIN_LEFT|| |
224 |
| -innerrel->reloptkind==RELOPT_JOINREL|| |
225 |
| -innerrel->rtekind!=RTE_RELATION|| |
226 |
| -innerrel->indexlist==NIL) |
227 |
| -return false; |
228 |
| - |
229 |
| -/* |
230 |
| - * We can't remove the join if any inner-rel attributes are used above the |
231 |
| - * join. |
232 |
| - * |
233 |
| - * Note that this test only detects use of inner-rel attributes in higher |
234 |
| - * join conditions and the target list. There might be such attributes in |
235 |
| - * pushed-down conditions at this join, too. We check that case below. |
236 |
| - * |
237 |
| - * As a micro-optimization, it seems better to start with max_attr and |
238 |
| - * count down rather than starting with min_attr and counting up, on the |
239 |
| - * theory that the system attributes are somewhat less likely to be wanted |
240 |
| - * and should be tested last. |
241 |
| - */ |
242 |
| -for (attroff=innerrel->max_attr-innerrel->min_attr; |
243 |
| -attroff >=0; |
244 |
| -attroff--) |
245 |
| -{ |
246 |
| -if (!bms_is_subset(innerrel->attr_needed[attroff],joinrel->relids)) |
247 |
| -return false; |
248 |
| -} |
249 |
| - |
250 |
| -/* |
251 |
| - * Similarly check that the inner rel doesn't produce any PlaceHolderVars |
252 |
| - * that will be used above the join. |
253 |
| - */ |
254 |
| -foreach(l,root->placeholder_list) |
255 |
| -{ |
256 |
| -PlaceHolderInfo*phinfo= (PlaceHolderInfo*)lfirst(l); |
257 |
| - |
258 |
| -if (bms_is_subset(phinfo->ph_eval_at,innerrel->relids)&& |
259 |
| -!bms_is_subset(phinfo->ph_needed,joinrel->relids)) |
260 |
| -return false; |
261 |
| -} |
262 |
| - |
263 |
| -/* |
264 |
| - * Search for mergejoinable clauses that constrain the inner rel against |
265 |
| - * either the outer rel or a pseudoconstant. If an operator is |
266 |
| - * mergejoinable then it behaves like equality for some btree opclass, so |
267 |
| - * it's what we want. The mergejoinability test also eliminates clauses |
268 |
| - * containing volatile functions, which we couldn't depend on. |
269 |
| - */ |
270 |
| -foreach(l,restrictlist) |
271 |
| -{ |
272 |
| -RestrictInfo*restrictinfo= (RestrictInfo*)lfirst(l); |
273 |
| - |
274 |
| -/* |
275 |
| - * If we find a pushed-down clause, it must have come from above the |
276 |
| - * outer join and it must contain references to the inner rel.(If it |
277 |
| - * had only outer-rel variables, it'd have been pushed down into the |
278 |
| - * outer rel.)Therefore, we can conclude that join removal is unsafe |
279 |
| - * without any examination of the clause contents. |
280 |
| - */ |
281 |
| -if (restrictinfo->is_pushed_down) |
282 |
| -return false; |
283 |
| - |
284 |
| -/* Ignore if it's not a mergejoinable clause */ |
285 |
| -if (!restrictinfo->can_join|| |
286 |
| -restrictinfo->mergeopfamilies==NIL) |
287 |
| -continue;/* not mergejoinable */ |
288 |
| - |
289 |
| -/* |
290 |
| - * Check if clause has the form "outer op inner" or "inner op outer". |
291 |
| - */ |
292 |
| -if (!clause_sides_match_join(restrictinfo,outerrel,innerrel)) |
293 |
| -continue;/* no good for these input relations */ |
294 |
| - |
295 |
| -/* OK, add to list */ |
296 |
| -clause_list=lappend(clause_list,restrictinfo); |
297 |
| -} |
298 |
| - |
299 |
| -/* Now examine the rel's restriction clauses for var = const clauses */ |
300 |
| -foreach(l,innerrel->baserestrictinfo) |
301 |
| -{ |
302 |
| -RestrictInfo*restrictinfo= (RestrictInfo*)lfirst(l); |
303 |
| - |
304 |
| -/* |
305 |
| - * Note: can_join won't be set for a restriction clause, but |
306 |
| - * mergeopfamilies will be if it has a mergejoinable operator and |
307 |
| - * doesn't contain volatile functions. |
308 |
| - */ |
309 |
| -if (restrictinfo->mergeopfamilies==NIL) |
310 |
| -continue;/* not mergejoinable */ |
311 |
| - |
312 |
| -/* |
313 |
| - * The clause certainly doesn't refer to anything but the given rel. |
314 |
| - * If either side is pseudoconstant then we can use it. |
315 |
| - */ |
316 |
| -if (bms_is_empty(restrictinfo->left_relids)) |
317 |
| -{ |
318 |
| -/* righthand side is inner */ |
319 |
| -restrictinfo->outer_is_left= true; |
320 |
| -} |
321 |
| -elseif (bms_is_empty(restrictinfo->right_relids)) |
322 |
| -{ |
323 |
| -/* lefthand side is inner */ |
324 |
| -restrictinfo->outer_is_left= false; |
325 |
| -} |
326 |
| -else |
327 |
| -continue; |
328 |
| - |
329 |
| -/* OK, add to list */ |
330 |
| -clause_list=lappend(clause_list,restrictinfo); |
331 |
| -} |
332 |
| - |
333 |
| -/* Now examine the indexes to see if we have a matching unique index */ |
334 |
| -if (relation_has_unique_index_for(root,innerrel,clause_list)) |
335 |
| -return true; |
336 |
| - |
337 |
| -/* |
338 |
| - * Some day it would be nice to check for other methods of establishing |
339 |
| - * distinctness. |
340 |
| - */ |
341 |
| -return false; |
342 |
| -} |
343 |
| - |
344 |
| -/* |
345 |
| - * generate_outer_only |
346 |
| - * Generate "join" paths when we have found the join is removable. |
347 |
| - */ |
348 |
| -staticvoid |
349 |
| -generate_outer_only(PlannerInfo*root,RelOptInfo*joinrel, |
350 |
| -RelOptInfo*outerrel) |
351 |
| -{ |
352 |
| -ListCell*lc; |
353 |
| - |
354 |
| -/* |
355 |
| - * For the moment, replicate all of the outerrel's paths as join paths. |
356 |
| - * Some of them might not really be interesting above the join, if they |
357 |
| - * have sort orderings that have no real use except to do a mergejoin for |
358 |
| - * the join we've just found we don't need. But distinguishing that case |
359 |
| - * probably isn't worth the extra code it would take. |
360 |
| - */ |
361 |
| -foreach(lc,outerrel->pathlist) |
362 |
| -{ |
363 |
| -Path*outerpath= (Path*)lfirst(lc); |
364 |
| - |
365 |
| -add_path(joinrel, (Path*) |
366 |
| -create_noop_path(root,joinrel,outerpath)); |
367 |
| -} |
368 |
| -} |
369 |
| - |
370 | 167 | /*
|
371 | 168 | * sort_inner_and_outer
|
372 | 169 | * Create mergejoin join paths by explicitly sorting both the outer and
|
|