9
9
*
10
10
*
11
11
* IDENTIFICATION
12
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.112 2005/08/27 18:04:49 tgl Exp $
12
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.113 2005/09/05 17:25:01 tgl Exp $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
@@ -130,6 +130,7 @@ static void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
130
130
Plan *
131
131
set_plan_references (Plan * plan , List * rtable )
132
132
{
133
+ bool copy_lefttree_tlist = false;
133
134
ListCell * l ;
134
135
135
136
if (plan == NULL )
@@ -218,14 +219,13 @@ set_plan_references(Plan *plan, List *rtable)
218
219
219
220
/*
220
221
* These plan types don't actually bother to evaluate their
221
- * targetlists (because they just return their unmodified
222
- * input tuples). The optimizer is lazy about creating really
223
- * valid targetlists for them --- it tends to just put in a
224
- * pointer to the child plan node's tlist. Hence, we leave
225
- * the tlist alone. In particular, we do not want to process
226
- * subplans in the tlist, since we will likely end up reprocessing
227
- * subplans that also appear in lower levels of the plan tree!
228
- *
222
+ * targetlists, because they just return their unmodified
223
+ * input tuples; so their targetlists should just be copies
224
+ * of their input plan nodes' targetlists. The actual copying
225
+ * has to be done after we've finalized the input node.
226
+ */
227
+ copy_lefttree_tlist = true;
228
+ /*
229
229
* Since these plan types don't check quals either, we should
230
230
* not find any qual expression attached to them.
231
231
*/
@@ -238,6 +238,7 @@ set_plan_references(Plan *plan, List *rtable)
238
238
* or quals. It does have live expressions for limit/offset,
239
239
* however.
240
240
*/
241
+ copy_lefttree_tlist = true;
241
242
Assert (plan -> qual == NIL );
242
243
fix_expr_references (plan , ((Limit * ) plan )-> limitOffset );
243
244
fix_expr_references (plan , ((Limit * ) plan )-> limitCount );
@@ -266,9 +267,10 @@ set_plan_references(Plan *plan, List *rtable)
266
267
267
268
/*
268
269
* Append, like Sort et al, doesn't actually evaluate its
269
- * targetlist or check quals, and we haven't bothered to give it
270
- * its own tlist copy. So, don't fix targetlist/qual. But do
271
- * recurse into child plans.
270
+ * targetlist or check quals, so don't fix targetlist/qual.
271
+ * But do recurse into child plans. (Unlike Sort et al, the
272
+ * correct tlist was made by createplan.c and we shouldn't
273
+ * replace it.)
272
274
*/
273
275
Assert (plan -> qual == NIL );
274
276
foreach (l , ((Append * ) plan )-> appendplans )
@@ -315,6 +317,20 @@ set_plan_references(Plan *plan, List *rtable)
315
317
sp -> plan = set_plan_references (sp -> plan , sp -> rtable );
316
318
}
317
319
320
+ /*
321
+ * If this is a non-projecting plan node, create a minimally valid
322
+ * targetlist for it. Someday we might need to make this look really
323
+ * real, with Vars referencing the input node's outputs, but for now
324
+ * the executor only cares that the tlist has the right TargetEntry
325
+ * fields (resname, resjunk etc) and exprType results. So we can
326
+ * get away with just copying the input node's tlist. (Note:
327
+ * createplan.c already did copy the input, but we have to do it
328
+ * over in case we removed a SubqueryScan node: the new input plan
329
+ * node might have extra resjunk fields.)
330
+ */
331
+ if (copy_lefttree_tlist )
332
+ plan -> targetlist = copyObject (plan -> lefttree -> targetlist );
333
+
318
334
return plan ;
319
335
}
320
336
0 commit comments