|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.68 2000/10/26 21:36:09 tgl Exp $ |
| 12 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.69 2001/01/09 03:48:51 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
16 | 16 | #include <sys/types.h>
|
17 | 17 |
|
18 | 18 | #include "postgres.h"
|
19 | 19 |
|
| 20 | +#include "nodes/makefuncs.h" |
20 | 21 | #include "nodes/nodeFuncs.h"
|
21 | 22 | #include "optimizer/clauses.h"
|
22 | 23 | #include "optimizer/planmain.h"
|
@@ -270,22 +271,75 @@ set_join_references(Join *join)
|
270 | 271 | * to refer to the tuples returned by its lefttree subplan.
|
271 | 272 | *
|
272 | 273 | * This is used for single-input plan types like Agg, Group, Result.
|
| 274 | + * |
| 275 | + * In most cases, we have to match up individual Vars in the tlist and |
| 276 | + * qual expressions with elements of the subplan's tlist (which was |
| 277 | + * generated by flatten_tlist() from these selfsame expressions, so it |
| 278 | + * should have all the required variables). There is an important exception, |
| 279 | + * however: a GROUP BY expression that is also an output expression will |
| 280 | + * have been pushed into the subplan tlist unflattened. We want to detect |
| 281 | + * this case and reference the subplan output directly. Therefore, check |
| 282 | + * for equality of the whole tlist expression to any subplan element before |
| 283 | + * we resort to picking the expression apart for individual Vars. |
273 | 284 | */
|
274 | 285 | static void
|
275 | 286 | set_uppernode_references(Plan *plan, Index subvarno)
|
276 | 287 | {
|
277 | 288 | Plan *subplan = plan->lefttree;
|
278 |
| - List *subplanTargetList; |
| 289 | + List *subplanTargetList, |
| 290 | + *outputTargetList, |
| 291 | + *l; |
279 | 292 |
|
280 | 293 | if (subplan != NULL)
|
281 | 294 | subplanTargetList = subplan->targetlist;
|
282 | 295 | else
|
283 | 296 | subplanTargetList = NIL;
|
284 | 297 |
|
285 |
| - plan->targetlist = (List *) |
286 |
| - replace_vars_with_subplan_refs((Node *) plan->targetlist, |
287 |
| - subvarno, |
288 |
| - subplanTargetList); |
| 298 | + outputTargetList = NIL; |
| 299 | + foreach (l, plan->targetlist) |
| 300 | + { |
| 301 | + TargetEntry *tle = (TargetEntry *) lfirst(l); |
| 302 | + TargetEntry *subplantle; |
| 303 | + Node *newexpr; |
| 304 | + |
| 305 | + subplantle = tlistentry_member(tle->expr, subplanTargetList); |
| 306 | + if (subplantle) |
| 307 | + { |
| 308 | + /* Found a matching subplan output expression */ |
| 309 | + Resdom *resdom = subplantle->resdom; |
| 310 | + Var *newvar; |
| 311 | + |
| 312 | + newvar = makeVar(subvarno, |
| 313 | + resdom->resno, |
| 314 | + resdom->restype, |
| 315 | + resdom->restypmod, |
| 316 | + 0); |
| 317 | + /* If we're just copying a simple Var, copy up original info */ |
| 318 | + if (subplantle->expr && IsA(subplantle->expr, Var)) |
| 319 | + { |
| 320 | + Var *subvar = (Var *) subplantle->expr; |
| 321 | + |
| 322 | + newvar->varnoold = subvar->varnoold; |
| 323 | + newvar->varoattno = subvar->varoattno; |
| 324 | + } |
| 325 | + else |
| 326 | + { |
| 327 | + newvar->varnoold = 0; |
| 328 | + newvar->varoattno = 0; |
| 329 | + } |
| 330 | + newexpr = (Node *) newvar; |
| 331 | + } |
| 332 | + else |
| 333 | + { |
| 334 | + /* No matching expression, so replace individual Vars */ |
| 335 | + newexpr = replace_vars_with_subplan_refs(tle->expr, |
| 336 | + subvarno, |
| 337 | + subplanTargetList); |
| 338 | + } |
| 339 | + outputTargetList = lappend(outputTargetList, |
| 340 | + makeTargetEntry(tle->resdom, newexpr)); |
| 341 | + } |
| 342 | + plan->targetlist = outputTargetList; |
289 | 343 |
|
290 | 344 | plan->qual = (List *)
|
291 | 345 | replace_vars_with_subplan_refs((Node *) plan->qual,
|
|
0 commit comments