+/*
+ * add_tlist_costs_to_plan
+ *
+ * Estimate the execution costs associated with evaluating the targetlist
+ * expressions, and add them to the cost estimates for the Plan node.
+ *
+ * If the tlist contains set-returning functions, also inflate the Plan's cost
+ * and plan_rows estimates accordingly. (Hence, this must be called *after*
+ * any logic that uses plan_rows to, eg, estimate qual evaluation costs.)
+ *
+ * Note: during initial stages of planning, we mostly consider plan nodes with
+ * "flat" tlists, containing just Vars. So their evaluation cost is zero
+ * according to the model used by cost_qual_eval() (or if you prefer, the cost
+ * is factored into cpu_tuple_cost). Thus we can avoid accounting for tlist
+ * cost throughout query_planner() and subroutines. But once we apply a
+ * tlist that might contain actual operators, sub-selects, etc, we'd better
+ * account for its cost. Any set-returning functions in the tlist must also
+ * affect the estimated rowcount.
+ *
+ * Once grouping_planner() has applied a general tlist to the topmost
+ * scan/join plan node, any tlist eval cost for added-on nodes should be
+ * accounted for as we create those nodes. Presently, of the node types we
+ * can add on later, only Agg, WindowAgg, and Group project new tlists (the
+ * rest just copy their input tuples) --- so make_agg(), make_windowagg() and
+ * make_group() are responsible for calling this function to account for their
+ * tlist costs.
+ */
+void
+add_tlist_costs_to_plan(PlannerInfo *root, Plan *plan, List *tlist)
+{
+ QualCost tlist_cost;
+ double tlist_rows;
+
+ cost_qual_eval(&tlist_cost, tlist, root);
+ plan->startup_cost += tlist_cost.startup;
+ plan->total_cost += tlist_cost.startup +
+ tlist_cost.per_tuple * plan->plan_rows;
+
+ tlist_rows = tlist_returns_set_rows(tlist);
+ if (tlist_rows > 1)
+ {
+ /*
+ * We assume that execution costs of the tlist proper were all
+ * accounted for by cost_qual_eval. However, it still seems
+ * appropriate to charge something more for the executor's general
+ * costs of processing the added tuples. The cost is probably less
+ * than cpu_tuple_cost, though, so we arbitrarily use half of that.
+ */
+ plan->total_cost += plan->plan_rows * (tlist_rows - 1) *
+ cpu_tuple_cost / 2;
+
+ plan->plan_rows *= tlist_rows;
+ }
+}
+