summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/subselect.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-03-26 13:05:49 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-03-26 13:05:51 -0400
commita65724dfa73db8b451d0c874a9161935a34a914e (patch)
tree04bdd460d3344447dcc29501e733d3dd6e8928aa /src/backend/optimizer/plan/subselect.c
parente648e77e25708874196326b6e4da30e7717156ab (diff)
Propagate pathkeys from CTEs up to the outer query.
If we know the sort order of a CTE's output, and it is relevant to the outer query, label the CTE's outer-query access path using those pathkeys. This may enable optimizations such as avoiding a sort in the outer query. The code for hoisting pathkeys into the outer query already exists for regular RTE_SUBQUERY subqueries, but it wasn't getting used for CTEs, possibly out of concern for maintaining an optimization fence between the CTE and the outer query. However, on the same arguments used for commit f7816aec2, there seems no harm in letting the outer query know what the inner query decided to do. In support of this, we now remember the best Path as well as Plan for each subquery for the rest of the planner run. There may be future applications for having that at hand, and it surely costs little to build one more List. Richard Guo (minor mods by me) Discussion: https://postgr.es/m/CAMbWs49xYd3f8CrE8-WW3--dV1zH_sDSDn-vs2DzHj81Wcnsew@mail.gmail.com
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r--src/backend/optimizer/plan/subselect.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index d6954a7e867..d5fa281b102 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -65,8 +65,8 @@ typedef struct inline_cte_walker_context
} inline_cte_walker_context;
-static Node *build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
- List *plan_params,
+static Node *build_subplan(PlannerInfo *root, Plan *plan, Path *path,
+ PlannerInfo *subroot, List *plan_params,
SubLinkType subLinkType, int subLinkId,
Node *testexpr, List *testexpr_paramids,
bool unknownEqFalse);
@@ -236,7 +236,8 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
plan = create_plan(subroot, best_path);
/* And convert to SubPlan or InitPlan format. */
- result = build_subplan(root, plan, subroot, plan_params,
+ result = build_subplan(root, plan, best_path,
+ subroot, plan_params,
subLinkType, subLinkId,
testexpr, NIL, isTopQual);
@@ -288,8 +289,8 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
/* ... and convert to SubPlan format */
hashplan = castNode(SubPlan,
- build_subplan(root, plan, subroot,
- plan_params,
+ build_subplan(root, plan, best_path,
+ subroot, plan_params,
ANY_SUBLINK, 0,
newtestexpr,
paramIds,
@@ -317,8 +318,8 @@ make_subplan(PlannerInfo *root, Query *orig_subquery,
* make it an InitPlan, as explained in the comments for make_subplan.
*/
static Node *
-build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
- List *plan_params,
+build_subplan(PlannerInfo *root, Plan *plan, Path *path,
+ PlannerInfo *subroot, List *plan_params,
SubLinkType subLinkType, int subLinkId,
Node *testexpr, List *testexpr_paramids,
bool unknownEqFalse)
@@ -539,9 +540,10 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
}
/*
- * Add the subplan and its PlannerInfo to the global lists.
+ * Add the subplan, its path, and its PlannerInfo to the global lists.
*/
root->glob->subplans = lappend(root->glob->subplans, plan);
+ root->glob->subpaths = lappend(root->glob->subpaths, path);
root->glob->subroots = lappend(root->glob->subroots, subroot);
splan->plan_id = list_length(root->glob->subplans);
@@ -1029,9 +1031,10 @@ SS_process_ctes(PlannerInfo *root)
splan->setParam = list_make1_int(paramid);
/*
- * Add the subplan and its PlannerInfo to the global lists.
+ * Add the subplan, its path, and its PlannerInfo to the global lists.
*/
root->glob->subplans = lappend(root->glob->subplans, plan);
+ root->glob->subpaths = lappend(root->glob->subpaths, best_path);
root->glob->subroots = lappend(root->glob->subroots, subroot);
splan->plan_id = list_length(root->glob->subplans);
@@ -3021,9 +3024,14 @@ SS_make_initplan_from_plan(PlannerInfo *root,
SubPlan *node;
/*
- * Add the subplan and its PlannerInfo to the global lists.
+ * Add the subplan and its PlannerInfo, as well as a dummy path entry, to
+ * the global lists. Ideally we'd save a real path, but right now our
+ * sole caller doesn't build a path that exactly matches the plan. Since
+ * we're not currently going to need the path for an initplan, it's not
+ * worth requiring construction of such a path.
*/
root->glob->subplans = lappend(root->glob->subplans, plan);
+ root->glob->subpaths = lappend(root->glob->subpaths, NULL);
root->glob->subroots = lappend(root->glob->subroots, subroot);
/*