Don't assume DISTINCT ON implies uniqueness when the tlist has SRFs query_is_distinct_for() treated a subquery's DISTINCT ON clause as proof that its output is unique over the DISTINCT ON columns, even if the targetlist contains set-returning functions. That's not true: when the query has an ORDER BY, the planner postpones evaluation of SRFs that are not DISTINCT ON or ORDER BY columns until after the Unique step, so the subquery can produce duplicates of the DISTINCT ON columns. Relying on this bogus uniqueness proof allowed join removal and unique-inner joins to produce wrong results.
Plain DISTINCT is not affected, since all tlist columns are DISTINCT columns there, and so any SRFs get expanded before the Unique step. To fix, make query_supports_distinctness() and query_is_distinct_for() refuse to prove distinctness via DISTINCT ON if the targetlist contains any SRFs. This is more conservative than necessary, since the SRFs are only postponed when there is an ORDER BY and none of them appear in a sort/group column, but it doesn't seem worth the trouble to check that precisely. Author: Richard Guo <[email protected]> Reviewed-by: Tom Lane <[email protected]> Discussion: https://postgr.es/m/CAMbWs4-hfd1Pyy_zBejsVUSy-3dx16rz2hgUakkKnAg3qg2q=q...@mail.gmail.com Backpatch-through: 14 Branch ------ REL_17_STABLE Details ------- https://git.postgresql.org/pg/commitdiff/a4eb938b33557193d90c1b396afd2c274e28b07e Modified Files -------------- src/backend/optimizer/plan/analyzejoins.c | 16 ++++++++++----- src/test/regress/expected/join.out | 33 +++++++++++++++++++++++++++++++ src/test/regress/sql/join.sql | 12 +++++++++++ 3 files changed, 56 insertions(+), 5 deletions(-)
