java.lang.Object
com.darkcollective.relix.optimizer.internal.SelectionComplement

public final class SelectionComplement extends Object
The predicate that keeps exactly the rows a selection drops.

Not ¬p. A selection keeps a row only when its predicate is TRUE, so the rows it drops are those where the predicate is FALSE or UNKNOWN — and ¬UNKNOWN is UNKNOWN, which a selection also drops. So σ ¬p keeps strictly fewer rows than R − σ p (R), and the gap is every row where p could not be decided:


   R = [(1, 10), (2, 500), (3, NULL)]

   R − σ amount > 100 (R)        →  (1, 10), (3, NULL)
   σ ¬(amount > 100) (R)         →  (1, 10)                 ← the NULL row is lost
   σ complement(amount > 100)(R) →  (1, 10), (3, NULL)
 

The correction is ¬p ∨ p IS UNKNOWN, and the second disjunct is a null test over the predicate's own truth value: a ConditionOperand evaluates to NULL exactly when the predicate it wraps is UNKNOWN, which is the one place the engine's third truth value becomes data.

The node is built directly, never as a call to IsNull. The function catalogue is discovered, so a library claiming that name at a higher priority would silently change what a rewrite built on it means — which is the hazard FunctionAccessGuardTest exists for. A predicate node needs no catalogue and cannot be shadowed.

The result is deliberately not simplified here. PRED-001 and friends run in the simplify phase, which is over by the time the rules that need this reach it, and a complement that folded itself would be a second simplifier to keep in step with the first.