postgres.git / summary / log / commit / refs

commit    b308eb3661bf41fa97e27909bf008871f438894c
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 a07392f00d6..d08018e4386 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -3428,16 +3428,18 @@ report_reduced_full_join(reduce_outer_joins_pass2_state *state2, 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)); @@ -3507,7 +3509,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, @@ -3848,7 +3851,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 @@ -3860,7 +3865,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: cdcec567da1b]