postgres.git / summary / log / commit / refs
commit 0da71d90d62308d12a789aad8a2a09223976fe88
Author: Richard Guo <rguo@postgresql.org>
Date: Mon Jul 20 03:13:11 2026 +0000
First released in: 16.15, 17.11, 18.6
Skip unnecessary get_relids_in_jointree() when there are no PHVs
Commit 1df9e8d96 made remove_useless_result_rtes() compute the set of
baserels in the jointree, to pass down to the find_dependent_phvs()
checks. But those checks are no-ops when the query contains no PHVs,
since find_dependent_phvs() and find_dependent_phvs_in_jointree() both
return early in that case. So we can avoid the
get_relids_in_jointree() scan altogether when root->glob->lastPHId is
zero, leaving baserels as NULL.
Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAMbWs49H275KzgZr3Cd1Hy+6Lmwp35bZ+5PrVc62k3HDLj6hNQ@mail.gmail.com
Backpatch-through: 16
src/backend/optimizer/prep/prepjointree.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 1ea72af7c73..72d39ba30fd 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -3888,16 +3888,18 @@ has_notnull_forced_var(PlannerInfo *root, List *forced_null_vars,
void
remove_useless_result_rtes(PlannerInfo *root)
{
- Relids baserels;
+ Relids baserels = NULL;
Relids dropped_outer_joins = NULL;
ListCell *cell;
/*
* We'll need the set of baserels in the jointree to perform
- * find_dependent_phvs() checks.
+ * find_dependent_phvs() checks. But if there are no PHVs anywhere in the
+ * query, those checks are no-ops, so we can skip the work.
*/
- baserels = get_relids_in_jointree((Node *) root->parse->jointree,
- false, false);
+ if (root->glob->lastPHId != 0)
+ baserels = get_relids_in_jointree((Node *) root->parse->jointree,
+ false, false);
/* Top level of jointree must always be a FromExpr */
Assert(IsA(root->parse->jointree, FromExpr));
@@ -3967,7 +3969,8 @@ remove_useless_result_rtes(PlannerInfo *root)
* (Note that in some cases, parent_quals points to the quals of a parent
* more than one level up in the tree.)
*
- * baserels is the set of base (non-join) RT indexes in the whole jointree.
+ * baserels is the set of base (non-join) RT indexes in the whole jointree;
+ * it can be NULL if the query contains no PHVs.
*/
static Node *
remove_useless_results_recurse(PlannerInfo *root, Node *jtnode,
@@ -4308,7 +4311,9 @@ remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
* already decided to remove those joins in remove_useless_result_rtes
* and not yet have cleaned their relid bits out of upper PHVs.
* But in general, it's the set of baserels that identify possible places
- * to evaluate a PHV, and we mustn't let that go to empty.
+ * to evaluate a PHV, and we mustn't let that go to empty. (The caller is
+ * allowed to pass baserels as NULL if the query contains no PHVs at all,
+ * since then there is no work to do anyway.)
*
* find_dependent_phvs should be used when we want to see if there are
* any such PHVs anywhere in the Query. Another use-case is to see if
@@ -4320,7 +4325,7 @@ remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
typedef struct
{
Relids relids; /* target relid, represented as a relid set */
- Relids baserels; /* set of base (non-OJ) RT indexes in query */
+ Relids baserels; /* base RT indexes in query, NULL if no PHVs */
int sublevels_up; /* current nesting level */
} find_dependent_phvs_context;
[parent: b087a88c40e4]