|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.145 2003/02/0900:30:39 tgl Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.146 2003/02/0923:57:19 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -144,6 +144,7 @@ subquery_planner(Query *parse, double tuple_fraction) |
144 | 144 | { |
145 | 145 | List*saved_initplan=PlannerInitPlan; |
146 | 146 | intsaved_planid=PlannerPlanId; |
| 147 | +boolhasOuterJoins; |
147 | 148 | Plan*plan; |
148 | 149 | List*newHaving; |
149 | 150 | List*lst; |
@@ -172,18 +173,25 @@ subquery_planner(Query *parse, double tuple_fraction) |
172 | 173 |
|
173 | 174 | /* |
174 | 175 | * Detect whether any rangetable entries are RTE_JOIN kind; if not, |
175 | | - * we can avoid the expense of doing flatten_join_alias_vars(). |
| 176 | + * we can avoid the expense of doing flatten_join_alias_vars(). Also |
| 177 | + * check for outer joins --- if none, we can skip reduce_outer_joins(). |
176 | 178 | * This must be done after we have done pull_up_subqueries, of course. |
177 | 179 | */ |
178 | 180 | parse->hasJoinRTEs= false; |
| 181 | +hasOuterJoins= false; |
179 | 182 | foreach(lst,parse->rtable) |
180 | 183 | { |
181 | 184 | RangeTblEntry*rte= (RangeTblEntry*)lfirst(lst); |
182 | 185 |
|
183 | 186 | if (rte->rtekind==RTE_JOIN) |
184 | 187 | { |
185 | 188 | parse->hasJoinRTEs= true; |
186 | | -break; |
| 189 | +if (IS_OUTER_JOIN(rte->jointype)) |
| 190 | +{ |
| 191 | +hasOuterJoins= true; |
| 192 | +/* Can quit scanning once we find an outer join */ |
| 193 | +break; |
| 194 | +} |
187 | 195 | } |
188 | 196 | } |
189 | 197 |
|
@@ -244,15 +252,23 @@ subquery_planner(Query *parse, double tuple_fraction) |
244 | 252 | } |
245 | 253 | parse->havingQual= (Node*)newHaving; |
246 | 254 |
|
| 255 | +/* |
| 256 | + * If we have any outer joins, try to reduce them to plain inner joins. |
| 257 | + * This step is most easily done after we've done expression preprocessing. |
| 258 | + */ |
| 259 | +if (hasOuterJoins) |
| 260 | +reduce_outer_joins(parse); |
| 261 | + |
247 | 262 | /* |
248 | 263 | * See if we can simplify the jointree; opportunities for this may come |
249 | 264 | * from having pulled up subqueries, or from flattening explicit JOIN |
250 | 265 | * syntax. We must do this after flattening JOIN alias variables, since |
251 | 266 | * eliminating explicit JOIN nodes from the jointree will cause |
252 | | - * get_relids_for_join() to fail. |
| 267 | + * get_relids_for_join() to fail. But it should happen after |
| 268 | + * reduce_outer_joins, anyway. |
253 | 269 | */ |
254 | 270 | parse->jointree= (FromExpr*) |
255 | | -preprocess_jointree(parse, (Node*)parse->jointree); |
| 271 | +simplify_jointree(parse, (Node*)parse->jointree); |
256 | 272 |
|
257 | 273 | /* |
258 | 274 | * Do the main planning. If we have an inherited target relation, |
|