v1-0001-Fix-bogus-calls-in-remove_self_join_rel.patch

application/octet-stream

Filename: v1-0001-Fix-bogus-calls-in-remove_self_join_rel.patch
Type: application/octet-stream
Part: 0
Message: The bogus calls in remove_self_join_rel()

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v1-0001
Subject: Fix bogus calls in remove_self_join_rel()
File+
src/backend/optimizer/plan/analyzejoins.c 10 2
From d06fc10fc3a5317a88a0576d9a2cfed1c10a4762 Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
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)