From 91b1872ff2de16cd353598edbc650a185e649226 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 14 Oct 2026 15:37:28 -0400 Subject: [PATCH] Clear more substructure of a dead relation during join removal. The tablesample and securityQuals subtrees of a RangeTblEntry can include Vars, which will cause trouble if they point at a removed rel and are visited during later processing. Hence, clear those fields during join removal, as we already do for the subquery field. remove_useless_outer_joins got this right for securityQuals but not tablesample, while remove_self_join_rel missed doing it for securityQuals. (It escapes trouble for tablesample only because we made a policy decision to never touch sampled relations for SJE.) Oversight in 2ebf25e7d. Back-patch to v16, like that commit (but the SJE issue only goes as far back as v18). Author: shihao zhong Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAGRkXqSOAT1yop44B8jwacL_91rxK=QuoU8Of3NLMb9NgAO2NA@mail.gmail.com Backpatch-through: 16 --- src/backend/optimizer/plan/analyzejoins.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 1fafca57004..ba1d7b3521c 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -151,13 +151,15 @@ remove_useless_outer_joins(PlannerInfo *root) * As in pull_up_simple_subquery, discard no-longer-needed subqueries. * This is not just an optimization, but is necessary to prevent * subsequent processing from descending into stale subtrees and - * seeing inconsistent data. Likewise discard any securityQuals of - * the removed rel. (Although simple_rte_array[] will be rebuilt - * shortly, we can still use it to find the RTE in the parse tree.) + * seeing inconsistent data. For the same reason, discard any + * tablesample and securityQuals subtrees of the removed rel. + * (Although simple_rte_array[] will be rebuilt shortly, we can still + * use it to find the RTE in the parse tree.) */ rte = root->simple_rte_array[innerrelid]; if (rte->rtekind == RTE_SUBQUERY) rte->subquery = NULL; + rte->tablesample = NULL; rte->securityQuals = NIL; /* @@ -1269,6 +1271,13 @@ remove_self_join_rel(PlannerInfo *root, ChangeVarNodes((Node *) root->append_rel_list, toRemove->relid, toKeep->relid, 0); + /* + * As in remove_useless_outer_joins, discard the securityQuals of the + * removed rel, so that later passes don't visit them. We know the kept + * rel has the same quals. (tablesample is already known NULL.) + */ + root->simple_rte_array[toRemove->relid]->securityQuals = NIL; + /* Clean up the quals that the substitution has messed with */ fixup_selfjoin_jointree(root, (Node *) root->parse->jointree, toKeep->relid,