On Fri, Jun 5, 2026 at 6:33 PM wenhui qiu <[email protected]> wrote: > Maybe I'm overthinking this, but one implementation detail worth considering > is whether pass1 should store the derived proof directly, rather than carrying > the original safe qual lists around.
I considered that. It would give the same answer, but I think carrying the raw quals is the better deal: pass2 runs find_nonnullable_vars only when it actually has forced-null vars in hand, so the common case of outer joins without any IS NULL quals pays nothing, whereas deriving the set in pass1 would walk every collected qual for every query containing an outer join. Also, no qual ever gets walked more than once in pass2: at each candidate join, the quals its own check consults and the quals pass1 propagates upward are complements (a LEFT join propagates the left child's quals and consults the right child's, and so on). A qual consulted by one join therefore never reaches an upper join's proof set, so pass2 walks each qual at most once. This is the same pruning correctness requires anyway: quals within a nullable side don't hold for null-extended rows, and that's exactly the side the join's check consults. - Richard
