wudidapaopao opened a new pull request, #25207:
URL: https://github.com/apache/datafusion/pull/25207

   ## Which issue does this PR close?
   
   - Closes #5830.
   
   ## Rationale for this change
   
   `simplify_predicates` (run by `PushDownFilter`) reduces the `>`/`>=` and the
   `<`/`<=` comparisons on a column to their most restrictive bound, but never
   compares the two groups with each other, and only looks for contradictions
   between equalities. So a filter that no row can satisfy still scans the 
table and
   evaluates the predicate per row, and comparisons already implied by an 
equality
   are still evaluated.
   
   | `WHERE` clause | Before | After |
   | --- | --- | --- |
   | `a > 3 AND a < 1` | `a > 3 AND a < 1` | `EmptyRelation` |
   | `a > 1 AND a < 1` | `a > 1 AND a < 1` | `EmptyRelation` |
   | `a >= 1 AND a < 1` | `a >= 1 AND a < 1` | `EmptyRelation` |
   | `a >= 1 AND a <= 1` | `a >= 1 AND a <= 1` | `a = 1` (unchanged, must not 
be pruned) |
   | `a = 7 AND a < 2` | `a = 7 AND a < 2` | `EmptyRelation` |
   | `a = 7 AND a != 7` | `a = 7 AND a != 7` | `EmptyRelation` |
   | `a = 7 AND a > 5` | `a = 7 AND a > 5` | `a = 7` |
   | `a = 7 AND a != 6` | `a = 7 AND a != 6` | `a = 7` |
   | `a > 10 AND a != 5` | `a > 10 AND a != 5` | `a > 10` |
   
   ## What changes are included in this PR?
   
   Three commits, the first of which is an existing bug this analysis would
   otherwise build on.
   
   1. `fix`: comparisons against a NULL literal were grouped and reduced like 
any
      other. `ScalarValue::try_cmp` follows sort order, where NULL is an 
ordinary
      value below every other one, rather than SQL three-valued logic, so
      `a > NULL AND a > 5` was reduced to `a > 5`. `a > NULL` never evaluates to
      true, so the conjunction matches no row while `a > 5` does. Queries do not
      reach this because `SimplifyExpressions` folds such comparisons 
beforehand,
      but `simplify_predicates` is public.
   
   2. `feat`: reason across the comparison groups of a column.
   
      - Contradicting bounds reduce the conjunction to `false`, so 
`EliminateFilter`
        and `PropagateEmptyRelation` can prune the plan being filtered. Bounds 
that
        meet at one value are unsatisfiable unless both admit it.
      - An equality pins the column to a single value, so it subsumes every 
other
        predicate that value satisfies and contradicts the rest.
      - `!=` predicates now take part: one is dropped once a bound already 
excludes
        its value, and one contradicting an equality reduces the conjunction to
        `false`.
   
      A column whose predicates contradict each other short circuits the whole
      list, since predicates on other columns cannot make the conjunction true
      again.
   
      `false` stands for a conjunction that never evaluates to true, which under
      three-valued logic includes evaluating to NULL. That is only equivalent 
for
      the predicates of a `Filter`, which keeps a row solely when they evaluate 
to
      true, and is where this runs.
   
   3. `test`: unit tests and `sqllogictest` cases for the above.
   
   ## What is the testing strategy for this PR?
   
   Unit tests in `simplify_predicates.rs` cover an equality being subsumed by 
and
   rejected by each of the six comparison operators, bounds meeting at one 
value for
   every combination of strict and inclusive comparisons, one column's 
contradiction
   discarding the predicates on other columns, `!=` being dropped and kept, and
   comparisons against NULL staying untouched. The last is only reachable from a
   unit test, as noted above.
   
   `simplify_predicates.slt` checks the plans produced for the same cases, and 
drops
   two `# TODO` markers that this PR implements.
   
   Verified with:
   
   ```text
   ./dev/rust_lint.sh
   cargo test -p datafusion-optimizer
   cargo test -p datafusion
   cargo test -p datafusion-cli
   cargo test --profile=ci --test sqllogictests
   ```
   
   ## Are there any user-facing changes?
   
   Filters that no row can satisfy no longer scan their input, and redundant
   comparisons are no longer evaluated per row. Result sets are unchanged, and 
there
   are no changes to public APIs.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to