Thread
-
Re: Use exact nullingrels matches for NestLoopParams
Richard Guo <guofenglinux@gmail.com> — 2025-11-17T07:28:45Z
On Tue, Nov 11, 2025 at 3:58 PM Richard Guo <guofenglinux@gmail.com> wrote: > Here is a patch that makes that change. It also removes the > NRM_SUBSET enum value, along with all remaining checks for it, since > it is no longer used. With the changes in 0001, we should now be able to use exact nullingrels matches in all cases when fixing up expressions of upper-level plan nodes that are not joins. Therefore, I think we can remove the nrm_match parameter from fix_upper_expr(), along with the corresponding field in fix_upper_expr_context. I've done that in 0002 (which will be squashed into 0001 when committed). > (I'm wondering if we have a way to identify the nullingrels added by > an outer join when fixing up its targetlist and qpqual. If so, we > might be able to switch to exact nullingrels matches for them and > thereby get rid of NRM_SUPERSET too.) After looking into this, I think it's quite challenging to determine the effects of an outer join when the join has been commuted with another one per outer join identity 3. In such cases, the Vars/PHVs in the join's targetlist and qpqual should have the same nullingrels they would have if the two joins had been done in syntactic order. Unfortunately, in setrefs.c we do not have enough information (such as the relevant SpecialJoinInfos) to determine that. For example, consider when we transform (A leftjoin B on (Pab)) leftjoin C on (Pbc) to A leftjoin (B leftjoin C on (Pbc)) on (Pab) For the now-upper A/B join, whose ojrelids is {3, 5}, the Vars from B in its targetlist and qpqual have nullingrels = {3}, and the Vars from C have nullingrels = {5}. In its inner plan's targetlist, however, both B and C Vars have empty nullingrels. The problem is that we have no reliable way in setrefs.c to determine which of the join's ojrelids should apply to which Vars. On the other hand, if we perform the transformation in the reverse order, then for the B/C join whose ojrelids is {4}, the C Vars in its targetlist and qpqual have nullingrels = {4, 5}, while in its inner plan's targetlist the C Vars have empty nullingrels. We have no reliable way to determine that {5} should also be applied to the C Vars. However, we can tighten the check somewhat. Currently, we check whether the jointype is JOIN_INNER and use NRM_SUPERSET if it is not. We can improve this by checking whether the Join node has non-empty ojrelids and using NRM_SUPERSET only in that case. This allows us to perform exact matches in more situations, such as the pushed-down B/C join in the first case. 0003 implements this. To support it, we record the outer-join relids in Join plan nodes (the related changes for adding ojrelids are adapted from the patch in [1]). This may seem like overengineering to have a new field just for this check, but the field also improves EXPLAIN (RANGE_TABLE) output by showing which outer-join relids are completed by each Join plan node. I expect that we will find other uses for the ojrelids information in the future. [1] https://postgr.es/m/3200728.1758662857@sss.pgh.pa.us - Richard