I thought about the strategy below in the past few days, and think it is better because it uses less cycles to get the same answer. IIUC, the related structs should be created during / after deconstruct_jointree rather than join_search_xx stage.
> The schemes I've been toying with tend to look more like putting a > PlaceHolderVar-ish wrapper around the Var or expression that represents > the below-the-join value. The wrapper node could carry any join ID > info that we find necessary. Just to confirm my understanding, the wrapper node should answer some questions like this. /* * rel_is_nullable_side * * For the given join ID joinrelids, return if the relid is in the nullable * side. */ static bool rel_is_nullable_side(PlannerInfo *root, Relids joinrelids, Index relid) { Assert(bms_is_member(relid, joinrelids)); ... } > The thing that I'm kind of stalled on is > how to define this struct so that it's not a big headache for join > strength reduction (which could remove the need for a wrapper altogether) or outer-join reordering (which makes it a bit harder to define which > join we think is the one nulling the value). > I think about the outer-join reorder case, can we just rely on SpecialJoinInfo.min_lefthands & min_righthands to get the answer? The attached patch is based on that. and I did some test in the patch as well, looks the answer is correct. What's more, if the above is correct and the calls of rel_is_nullable_side is small, do we still need think about more effective data struct? Thanks! -- Best Regards Andy Fan
not_null_based_on_special_joininfo.diff
Description: Binary data