Class SelectionMergePass
SEL-002 — adjacent selections
σ(A)(σ(B)(R)) → σ(A ∧ B)(R). Multiple adjacent selections are collapsed
in a single pass: σ(A)(σ(B)(σ(C)(R))) → σ(A ∧ B ∧ C)(R) (two firings,
bottom-up). This is the inverse of SelectionSplitPass.
SEL-010 — a set operation over two selections of one input
σ i (A) ∪ σ q (A) → δ σ (i ∨ q) (A)
σ i (A) ∩ σ q (A) → δ σ (i ∧ q) (A)
σ i (A) − σ q (A) → δ σ (i ∧ (¬q ∨ q IS UNKNOWN)) (A)
When both branches filter the same input, the operation is doing by
row-matching what one predicate does by evaluation. The rewrite deletes a blocking
operator outright — ∪ and ∩ each buffer a hash set of one side — and
leaves one filtered read where there were two. It also restores pushdown: the SQL
renderer folds σ but not UNION, so the set operation is a boundary the fold
cannot cross, and one WHERE crosses it.
The two inputs are compared with AstEquivalence, which is location-free, so
the same sub-expression written out twice matches where record equality never could.
Why the δ, and when it is dropped
∪ and ∩ declare MaterializationMode.SET
and PropertyDeriver reports their output duplicate-free on the strength of
that declaration — which DIST-001 then reads. A merged σ over a bag input does
not de-duplicate, so handing one back bare would make a claim the input need
not honour, and a δ removed above it would not come back. The δ is therefore emitted
unless the input is provably duplicate-free, which is the same question
DIST-001 asks; either way the set operation is gone.
Gates
- Reproducibility. The rewrite evaluates the input once where the query
evaluated it twice, and evaluates each predicate once per row rather than once
per branch, so both branches must be deterministic
(
DeterminismSourceon the context). −is noti ∧ ¬q. A row whoseqis UNKNOWN is absent fromσq(A)and so kept by the difference, while¬UNKNOWNis UNKNOWN and a bare¬qdrops it.SelectionComplementwrites the correction.⊎is excluded — bag union, so the multiplicities are the answer — and so is∆, which would need an XOR the predicate language does not have.
Phase placement
SEL-010 is the exact inverse of SEL-009, which distributes a σ over
the set operations. They are in different phases for the reason
SEL-001/SEL-002 are: put both in one phase and the sweep trades the two
shapes forever. SEL-009 runs in pushdown and this pass in
cleanup, which is also the useful order — a σ that was distributed and could
then be carried no further is merged back into one.
This class is package-private and stateless; call
apply(RelNode, String, SchemaAnnotations, OptimizationContext) as a
static method.
-
Method Summary