aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/costsize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/costsize.c')
-rw-r--r--src/backend/optimizer/path/costsize.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 5e5732f6e12..fb28e6411aa 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -1415,10 +1415,12 @@ cost_tidrangescan(Path *path, PlannerInfo *root,
*
* 'baserel' is the relation to be scanned
* 'param_info' is the ParamPathInfo if this is a parameterized path, else NULL
+ * 'trivial_pathtarget' is true if the pathtarget is believed to be trivial.
*/
void
cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root,
- RelOptInfo *baserel, ParamPathInfo *param_info)
+ RelOptInfo *baserel, ParamPathInfo *param_info,
+ bool trivial_pathtarget)
{
Cost startup_cost;
Cost run_cost;
@@ -1458,6 +1460,22 @@ cost_subqueryscan(SubqueryScanPath *path, PlannerInfo *root,
path->path.startup_cost = path->subpath->startup_cost;
path->path.total_cost = path->subpath->total_cost;
+ /*
+ * However, if there are no relevant restriction clauses and the
+ * pathtarget is trivial, then we expect that setrefs.c will optimize away
+ * the SubqueryScan plan node altogether, so we should just make its cost
+ * and rowcount equal to the input path's.
+ *
+ * Note: there are some edge cases where createplan.c will apply a
+ * different targetlist to the SubqueryScan node, thus falsifying our
+ * current estimate of whether the target is trivial, and making the cost
+ * estimate (though not the rowcount) wrong. It does not seem worth the
+ * extra complication to try to account for that exactly, especially since
+ * that behavior falsifies other cost estimates as well.
+ */
+ if (qpquals == NIL && trivial_pathtarget)
+ return;
+
get_restriction_qual_cost(root, baserel, param_info, &qpqual_cost);
startup_cost = qpqual_cost.startup;