From: Richard Guo Date: Mon, 20 Jul 2026 03:13:11 +0000 (+0900) Subject: Skip unnecessary get_relids_in_jointree() when there are no PHVs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0da71d90d62308d12a789aad8a2a09223976fe88;p=thirdparty%2Fpostgresql.git 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 Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAMbWs49H275KzgZr3Cd1Hy+6Lmwp35bZ+5PrVc62k3HDLj6hNQ@mail.gmail.com Backpatch-through: 16 --- 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;