99 *
1010 *
1111 * 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 $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -130,6 +130,7 @@ static void set_sa_opfuncid(ScalarArrayOpExpr *opexpr);
130130Plan *
131131set_plan_references (Plan * plan ,List * rtable )
132132{
133+ bool copy_lefttree_tlist = false;
133134ListCell * l ;
134135
135136if (plan == NULL )
@@ -218,14 +219,13 @@ set_plan_references(Plan *plan, List *rtable)
218219
219220/*
220221 * 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+ /*
229229 * Since these plan types don't check quals either, we should
230230 * not find any qual expression attached to them.
231231 */
@@ -238,6 +238,7 @@ set_plan_references(Plan *plan, List *rtable)
238238 * or quals. It does have live expressions for limit/offset,
239239 * however.
240240 */
241+ copy_lefttree_tlist = true;
241242Assert (plan -> qual == NIL );
242243fix_expr_references (plan , ((Limit * )plan )-> limitOffset );
243244fix_expr_references (plan , ((Limit * )plan )-> limitCount );
@@ -266,9 +267,10 @@ set_plan_references(Plan *plan, List *rtable)
266267
267268/*
268269 * 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.)
272274 */
273275Assert (plan -> qual == NIL );
274276foreach (l , ((Append * )plan )-> appendplans )
@@ -315,6 +317,20 @@ set_plan_references(Plan *plan, List *rtable)
315317sp -> plan = set_plan_references (sp -> plan ,sp -> rtable );
316318}
317319
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+
318334return plan ;
319335}
320336