Don't remove an RTE_RESULT needed by a nested PlaceHolderVar

When remove_useless_result_rtes() removes an RTE_RESULT, any
PlaceHolderVars that were to be evaluated there must be evaluated
somewhere else.  If the RTE_RESULT is the nullable side of an outer
join, there is no other place that would preserve the PHVs' nulling
behavior, so find_dependent_phvs() refuses the removal if any such PHV
exists anywhere in the query.  If the RTE_RESULT is a child of an
inner join, its PHVs can instead be evaluated at the join of all its
sibling rels, unless a sibling needs them before that join is formed.
find_dependent_phvs_in_jointree() checks for that by looking for such
PHVs in the join quals and LATERAL RTEs of the siblings.

That misses a PHV that is evaluated at some but not all of the sibling
rels and contains one of the RTE_RESULT's PHVs.  Such a PHV can appear
anywhere in the query, such as in the targetlist.  This can happen
when pulled-up expressions are wrapped in PHVs because of outer joins
or grouping sets.  Once the RTE_RESULT is removed, the outer PHV needs
a value that is only available at a join above its own evaluation
level.  The outer PHV's rel thus becomes laterally dependent on the
other sibling rels.  If one of those rels laterally references it in
turn, we end up with a rel that is laterally dependent on itself,
causing an assertion failure in create_lateral_join_info().

To fix, also search the whole query for PHVs that are evaluated at
some but not all of the sibling rels, and refuse to remove the
RTE_RESULT if any of them contains one of its PHVs.  An outer PHV that
is evaluated at all of the sibling rels is not a problem, since the
moved PHV is available there, so we don't block removal in that common
case.

Back-patch to all supported branches.

Author: Richard Guo <[email protected]>
Reviewed-by: Ayush Tiwari <[email protected]>
Discussion: 
https://postgr.es/m/cambws4_hlosw8_sepp_3emytlx8oc4zezevypyprszpomhd...@mail.gmail.com
Backpatch-through: 14

Branch
------
REL_16_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/d87257b2cddc9a0f80bbb80d3190686aa983d9cd

Modified Files
--------------
src/backend/optimizer/prep/prepjointree.c | 69 ++++++++++++++++++++++++-
src/test/regress/expected/join.out        | 83 +++++++++++++++++++++++++++++++
src/test/regress/sql/join.sql             | 34 +++++++++++++
3 files changed, 184 insertions(+), 2 deletions(-)

Reply via email to