@@ -1045,7 +1045,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1045
1045
double sub_limit_tuples ;
1046
1046
AttrNumber * groupColIdx = NULL ;
1047
1047
bool need_tlist_eval = true;
1048
- QualCost tlist_cost ;
1049
1048
Path * cheapest_path ;
1050
1049
Path * sorted_path ;
1051
1050
Path * best_path ;
@@ -1355,27 +1354,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1355
1354
1356
1355
/*
1357
1356
* Also, account for the cost of evaluation of the sub_tlist.
1358
- *
1359
- * Up to now, we have only been dealing with "flat" tlists,
1360
- * containing just Vars. So their evaluation cost is zero
1361
- * according to the model used by cost_qual_eval() (or if you
1362
- * prefer, the cost is factored into cpu_tuple_cost). Thus we
1363
- * can avoid accounting for tlist cost throughout
1364
- * query_planner() and subroutines. But now we've inserted a
1365
- * tlist that might contain actual operators, sub-selects, etc
1366
- * --- so we'd better account for its cost.
1367
- *
1368
- * Below this point, any tlist eval cost for added-on nodes
1369
- * should be accounted for as we create those nodes.
1370
- * Presently, of the node types we can add on, only Agg,
1371
- * WindowAgg, and Group project new tlists (the rest just copy
1372
- * their input tuples) --- so make_agg(), make_windowagg() and
1373
- * make_group() are responsible for computing the added cost.
1357
+ * See comments for add_tlist_costs_to_plan() for more info.
1374
1358
*/
1375
- cost_qual_eval (& tlist_cost , sub_tlist , root );
1376
- result_plan -> startup_cost += tlist_cost .startup ;
1377
- result_plan -> total_cost += tlist_cost .startup +
1378
- tlist_cost .per_tuple * result_plan -> plan_rows ;
1359
+ add_tlist_costs_to_plan (root , result_plan , sub_tlist );
1379
1360
}
1380
1361
else
1381
1362
{
@@ -1815,6 +1796,61 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1815
1796
return result_plan ;
1816
1797
}
1817
1798
1799
+ /*
1800
+ * add_tlist_costs_to_plan
1801
+ *
1802
+ * Estimate the execution costs associated with evaluating the targetlist
1803
+ * expressions, and add them to the cost estimates for the Plan node.
1804
+ *
1805
+ * If the tlist contains set-returning functions, also inflate the Plan's cost
1806
+ * and plan_rows estimates accordingly. (Hence, this must be called *after*
1807
+ * any logic that uses plan_rows to, eg, estimate qual evaluation costs.)
1808
+ *
1809
+ * Note: during initial stages of planning, we mostly consider plan nodes with
1810
+ * "flat" tlists, containing just Vars. So their evaluation cost is zero
1811
+ * according to the model used by cost_qual_eval() (or if you prefer, the cost
1812
+ * is factored into cpu_tuple_cost). Thus we can avoid accounting for tlist
1813
+ * cost throughout query_planner() and subroutines. But once we apply a
1814
+ * tlist that might contain actual operators, sub-selects, etc, we'd better
1815
+ * account for its cost. Any set-returning functions in the tlist must also
1816
+ * affect the estimated rowcount.
1817
+ *
1818
+ * Once grouping_planner() has applied a general tlist to the topmost
1819
+ * scan/join plan node, any tlist eval cost for added-on nodes should be
1820
+ * accounted for as we create those nodes. Presently, of the node types we
1821
+ * can add on later, only Agg, WindowAgg, and Group project new tlists (the
1822
+ * rest just copy their input tuples) --- so make_agg(), make_windowagg() and
1823
+ * make_group() are responsible for calling this function to account for their
1824
+ * tlist costs.
1825
+ */
1826
+ void
1827
+ add_tlist_costs_to_plan (PlannerInfo * root , Plan * plan , List * tlist )
1828
+ {
1829
+ QualCost tlist_cost ;
1830
+ double tlist_rows ;
1831
+
1832
+ cost_qual_eval (& tlist_cost , tlist , root );
1833
+ plan -> startup_cost += tlist_cost .startup ;
1834
+ plan -> total_cost += tlist_cost .startup +
1835
+ tlist_cost .per_tuple * plan -> plan_rows ;
1836
+
1837
+ tlist_rows = tlist_returns_set_rows (tlist );
1838
+ if (tlist_rows > 1 )
1839
+ {
1840
+ /*
1841
+ * We assume that execution costs of the tlist proper were all
1842
+ * accounted for by cost_qual_eval. However, it still seems
1843
+ * appropriate to charge something more for the executor's general
1844
+ * costs of processing the added tuples. The cost is probably less
1845
+ * than cpu_tuple_cost, though, so we arbitrarily use half of that.
1846
+ */
1847
+ plan -> total_cost += plan -> plan_rows * (tlist_rows - 1 ) *
1848
+ cpu_tuple_cost / 2 ;
1849
+
1850
+ plan -> plan_rows *= tlist_rows ;
1851
+ }
1852
+ }
1853
+
1818
1854
/*
1819
1855
* Detect whether a plan node is a "dummy" plan created when a relation
1820
1856
* is deemed not to need scanning due to constraint exclusion.
0 commit comments