Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #26132 +/- ##
==========================================
+ Coverage 82.74% 82.78% +0.03%
==========================================
Files 1147 1148 +1
Lines 449767 451217 +1450
Branches 449767 451217 +1450
==========================================
+ Hits 372157 373521 +1364
+ Misses 54942 54939 -3
- Partials 22668 22757 +89 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
jayzhan211
left a comment
There was a problem hiding this comment.
Thanks @xudong963 , 1 suggestion
| Ok(result) | ||
| } | ||
|
|
||
| fn simplify_disjunction( |
There was a problem hiding this comment.
simplify_disjunction splits one binary OR and recurses with depth + 1, so a left-deep a OR b OR c ... spends one depth level per disjunct. Disjuncts past MAX_DISJUNCTION_DEPTH are never checked: x >= 5000 AND (<120 disjoint ranges below 5000>) still keeps 27 impossible disjuncts (and the scan) after the default 3 passes, and the result depends on max_passes. Flattening the chain makes depth count AND/OR nesting only. With the change below that query plans to EmptyRelation, and predicates.slt / simplify_predicate*.slt still pass.
- let Expr::BinaryExpr(BinaryExpr {
- left,
- op: Operator::Or,
- right,
- }) = predicate
- else {
- return Ok(predicate);
- };
+ if !matches!(
+ predicate,
+ Expr::BinaryExpr(BinaryExpr {
+ op: Operator::Or,
+ ..
+ })
+ ) {
+ return Ok(predicate);
+ }
...
- let left = simplify_branch(*left)?;
- let right = simplify_branch(*right)?;
- Ok(if is_false(&left) {
- right
- } else if is_false(&right) {
- left
- } else {
- left.or(right)
- })
+ // Flatten `a OR b OR c` so the depth limit counts AND/OR nesting, not disjuncts.
+ let mut branches = Vec::new();
+ for branch in split_binary_owned(predicate, Operator::Or) {
+ let branch = simplify_branch(branch)?;
+ if !is_false(&branch) {
+ branches.push(branch);
+ }
+ }
+ Ok(disjunction(branches).unwrap_or_else(|| lit(false)))
Which issue does this PR close?
Rationale for this change
An outer range can make every branch of an OR impossible, but the logical optimizer currently considers the direct comparisons and the disjunction independently. For example,
x >= 10 AND ((x >= 1 AND x < 3) OR (x >= 5 AND x < 7))retains a scan despite never matching a row.This matters for a
UNION ALLcontaining historical backfill branches: a request outside their time windows should eliminate those branches before physical planning calls their table providers, including when the query has an outerORDER BY ... LIMIT.What changes are included in this PR?
EmptyRelationbefore provider pushdown; anExactprovider must not absorb FALSE into its scan and still receive ascan()call.What is the testing strategy for this PR?
simplify_predicate_disjunctions.slt: empty intersections, gaps, partial overlap, retained outer assumptions, equality/inequality predicates, NULL, NOT, casts, arithmetic, timestamp precision/time zones, and union branch removal with an outer sort/limit.simplify_predicates.slt: existing regression coverage and an updated plan expectation for independently simplified OR arms.scan()returns an error verifies that the eliminated union branch is never scanned under Exact, Inexact, or Unsupported pushdown.predicates.sltand TPC-H Q19 plan/answer tests verify that unchanged OR branches retain their predicate order. The two CI failures were due to predicate-order differences; their existing plan expectations now pass without snapshot updates.All checks above passed (
predicates.sltalso matchessimplify_predicates.slt). TPC-H Q19 was additionally run with CI's SF0.1 data and a temporary SQL logic test wrapper including only its table setup, plan, answer, and cleanup files. The full lint script used an isolated currentcargo-auditand a temporary workspace boundary fordev/depcheckbecause this checkout is nested inside another Cargo workspace. On the final lint run,cargo-audit --no-fetchused the advisory database and registry index downloaded earlier the same day because local DNS could not resolveindex.crates.io. No tooling or manifest changes are included in the patch. Only targeted tests were run, not the full workspace test suite.Are there any user-facing changes?
Queries with contradictory ranges across AND/OR can avoid planning and scanning impossible inputs. Partial simplification retains all matching rows. No public API or configuration changes.
This reasoning is specific to filter truth sets; it does not change nullable Boolean projection results or derive cross-column date/timestamp equivalences.