On Tue, Jun 16, 2026 at 10:58 AM Tender Wang <[email protected]> wrote: > It was distributed to (rel:2, table t), but I think "[phrels] > Bitmapset [4 3 2]" is incorrect. After leftjoin is removed, we no > longer need rel=4 (outerjoin) and rel=3 (t r). > But the qual has already been distributed to the (rel: 2) when > deconstruct_jointree (). Then the qual is inherited by its child(table > p) > It seems that we have no logic to process this distributed > restrictinfo in remove_useless_joins().
When removing the left join, remove_rel_from_query() fixes up the relid sets of RestrictInfos and EquivalenceMembers, and the canonical PlaceHolderVars, but it does not rewrite the PlaceHolderVars embedded in clause and EC-member expressions. This is usually fine, because later processing consults those relid sets rather than the embedded PHVs. The trouble is that such an expression can later be translated for an appendrel child and have its relids recomputed by pull_varnos(). If the embedded PlaceHolderVar's phrels still mentions the removed relation, pull_varnos() folds it back in, so the rebuilt clause references a no-longer-existent rel. That produces a parameterized path keyed on the removed relation, which trips the assertion. I think we can fix it by stripping the removed relids from the PHVs in surviving rels' baserestrictinfo and in EquivalenceClass member expressions. See attached. (I went back and forth on instead making pull_varnos() robust to the stale phrels, but that turned out fragile: it can't reliably distinguish a removed relid from a not-yet-built appendrel child, and it broke unrelated partitionwise-join plans.) Thoughts? - Richard
v1-0001-Strip-removed-relation-references-from-PlaceHolde.patch
Description: Binary data
