From d06fc10fc3a5317a88a0576d9a2cfed1c10a4762 Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Thu, 23 Apr 2026 11:19:25 +0900 Subject: [PATCH v1] Fix bogus calls in remove_self_join_rel() remove_self_join_rel() called adjust_relid_set() on all_result_relids and leaf_result_relids but threw away the return value. Since adjust_relid_set() returns a freshly-built Relids and does not modify the input in place, the calls did nothing. This has been the case since the SJE feature went in (commit fc069a3a6). There has been no observable misbehavior, because the relid being passed is guaranteed not to be a member of either set: those sets contain only the query's top-level target relation, which remove_self_joins_recurse() rejects as an SJE candidate to preserve the EvalPlanQual mechanism, plus inheritance children of the target relation, which are RELOPT_OTHER_MEMBER_RELs and so never appear in the joinlist that SJE scans for candidates. Even with the result assigned, the calls would be no-ops in practice. Rather than make the calls do the cleanup they pretend to do, replace them with assertions of the invariant. Any future loosening of the SJE candidate filter -- for instance to allow eliminating a result relation under provable conditions -- will trip the assertion and force whoever does it to revisit this code. --- src/backend/optimizer/plan/analyzejoins.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 03056bdf3e0..494b9ee0716 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -1994,8 +1994,16 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark, ChangeVarNodesExtended((Node *) root->processed_tlist, toRemove->relid, toKeep->relid, 0, replace_relid_callback); - adjust_relid_set(root->all_result_relids, toRemove->relid, toKeep->relid); - adjust_relid_set(root->leaf_result_relids, toRemove->relid, toKeep->relid); + /* + * No need to touch all_result_relids or leaf_result_relids: every relid + * in those sets is either the query's top-level target relation, which + * remove_self_joins_recurse() rejects as an SJE candidate (the EPQ + * mechanism requires the target rel to survive), or an inheritance child + * of it, which is a RELOPT_OTHER_MEMBER_REL and so never appears in the + * joinlist that SJE scans. toRemove->relid therefore cannot be a member. + */ + Assert(!bms_is_member(toRemove->relid, root->all_result_relids)); + Assert(!bms_is_member(toRemove->relid, root->leaf_result_relids)); /* * There may be references to the rel in root->fkey_list, but if so, -- 2.39.5 (Apple Git-154)