On Thu, Sep 3, 2026 at 6:39 PM Tender Wang <[email protected]> wrote:
> I also noticed that the resulting plan contains a duplicated filter:

> This is not introduced by v1; I can reproduce the same duplicate qual on
> pg16.14 as well, so it seems to be a pre-existing issue.

Right, this is a pre-existing issue, and is exposed by the new test
case.

+            ->  Subquery Scan on t3
+                  Filter: ((b.q1 = t3.cnt) AND (b.q1 = t3.cnt))

I looked into it.  What happens here is that outer-join identity 3
permits the join to t3 to commute with the a/b left join, so we
generate multiple clones of "b.q1 = t3.cnt", differing in the
nullingrels of b.q1.  Only one of them should be applied in any given
plan.  However, when movable join clauses are pushed down into a
parameterized path, we fail to choose among the clones.  In this
example, t3's lateral reference to a PlaceHolderVar evaluated at the
a/b join forces every path for t3 to be parameterized by a set that
includes that outer join's relid, making both clones movable into the
scan.  The same thing can also happen for clauses moved down into a
parameterized join.

I think we need to fix this.  It wastes effort evaluating the same
qual clause repeatedly.  What is worse, it applies the clause's
selectivity multiple times, underestimating the result's row count.

Attached is a patch that teaches get_baserel_parampathinfo and
get_joinrel_parampathinfo to check incompatible_relids.  A clone
should not be enforced if an outer join it is incompatible with has
already been computed.

Thoughts?

- Richard

Attachment: v1-0001-Fix-duplicate-qual-clauses-in-parameterized-paths.patch
Description: Binary data

Reply via email to