Plan *
 set_plan_references(Plan *plan, List *rtable)
 {
-       bool            copy_lefttree_tlist = false;
        ListCell   *l;
 
        if (plan == NULL)
 
                        /*
                         * These plan types don't actually bother to evaluate their
-                        * targetlists, because they just return their unmodified
-                        * input tuples; so their targetlists should just be copies
-                        * of their input plan nodes' targetlists.  The actual copying
-                        * has to be done after we've finalized the input node.
-                        */
-                       copy_lefttree_tlist = true;
-                       /*
+                        * targetlists (because they just return their unmodified
+                        * input tuples).  The optimizer is lazy about creating really
+                        * valid targetlists for them --- it tends to just put in a
+                        * pointer to the child plan node's tlist.  Hence, we leave
+                        * the tlist alone.  In particular, we do not want to process
+                        * subplans in the tlist, since we will likely end up reprocessing
+                        * subplans that also appear in lower levels of the plan tree!
+                        *
                         * Since these plan types don't check quals either, we should
                         * not find any qual expression attached to them.
                         */
                         * or quals.  It does have live expressions for limit/offset,
                         * however.
                         */
-                       copy_lefttree_tlist = true;
                        Assert(plan->qual == NIL);
                        fix_expr_references(plan, ((Limit *) plan)->limitOffset);
                        fix_expr_references(plan, ((Limit *) plan)->limitCount);
 
                        /*
                         * Append, like Sort et al, doesn't actually evaluate its
-                        * targetlist or check quals, so don't fix targetlist/qual.
-                        * But do recurse into child plans.  (Unlike Sort et al, the
-                        * correct tlist was made by createplan.c and we shouldn't
-                        * replace it.)
+                        * targetlist or check quals, and we haven't bothered to give it
+                        * its own tlist copy. So, don't fix targetlist/qual. But do
+                        * recurse into child plans.
                         */
                        Assert(plan->qual == NIL);
                        foreach(l, ((Append *) plan)->appendplans)
                sp->plan = set_plan_references(sp->plan, sp->rtable);
        }
 
-       /*
-        * If this is a non-projecting plan node, create a minimally valid
-        * targetlist for it.  Someday we might need to make this look really
-        * real, with Vars referencing the input node's outputs, but for now
-        * the executor only cares that the tlist has the right TargetEntry
-        * fields (resname, resjunk etc) and exprType results.  So we can
-        * get away with just copying the input node's tlist.  (Note:
-        * createplan.c already did copy the input, but we have to do it
-        * over in case we removed a SubqueryScan node: the new input plan
-        * node might have extra resjunk fields.)
-        */
-       if (copy_lefttree_tlist)
-               plan->targetlist = copyObject(plan->lefttree->targetlist);
-
        return plan;
 }
 
        if (plan->scan.plan.qual != NIL)
                return false;
 
+       if (list_length(plan->scan.plan.targetlist) !=
+               list_length(plan->subplan->targetlist))
+               return false;                   /* tlists not same length */
+
        attrno = 1;
        forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
        {
                attrno++;
        }
 
-       if (lp)
-               return false;                   /* parent tlist longer than child */
-
-       /* extra child items are OK only if all are resjunk */
-       for_each_cell(lc, lc)
-       {
-               TargetEntry *ctle = (TargetEntry *) lfirst(lc);
-
-               if (!ctle->resjunk)
-                       return false;
-       }
-
        return true;
 }