peter-toth opened a new pull request, #57357:
URL: https://github.com/apache/spark/pull/57357

   ### What changes were proposed in this pull request?
   
   This PR guards the `SupportsPushDownV2Filters` branch of 
`PushDownUtils.pushFilters` so that only deterministic filters are translated 
and pushed to the data source; nondeterministic filters are kept as post-scan 
filters and evaluated by Spark after the scan. This mirrors the fix made for 
`SupportsPushDownCatalystFilters` in #57235 (SPARK-58112).
   
   ### Why are the changes needed?
   
   Before this change the `SupportsPushDownV2Filters` branch translated and 
pushed every conjunct, and `V2ExpressionBuilder` translates `Rand`, so a 
predicate such as `rand() > 0.5` was pushed to a V2 source.
   
   Pushing a nondeterministic predicate is unsound: the data source may 
evaluate it a different number of times or at a different point than Spark, and 
a *partial* push — a predicate used for pruning yet also returned for post-scan 
re-evaluation (e.g. a parquet row group filter, which is an explicitly 
documented mode of `SupportsPushDownV2Filters#pushedPredicates`) — evaluates 
the predicate twice with different results, which can change query results.
   
   This is the same class of problem that #57235 (SPARK-58112) fixed for 
`SupportsPushDownCatalystFilters`. The other pushdown paths already avoid it:
   - `SupportsPushDownFilters` (V1 `sources.Filter`): nondeterministic 
predicates are untranslatable to `sources.Filter`, so they fall through to 
post-scan.
   - the iterative `PartitionPredicate` second pass: guarded by 
`PushDownUtils.isPushablePartitionFilter` (`f.deterministic`).
   
   Only the `SupportsPushDownV2Filters` first-pass push was left unguarded; 
this closes that gap so all pushdown paths handle nondeterministic filters 
consistently.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. Data sources implementing `SupportsPushDownV2Filters` will no longer 
receive nondeterministic filters through `pushPredicates`; those filters remain 
in Spark as post-scan filters. For a source that fully enforced such a 
predicate this is an internal change only; for a source that treated a pushed 
nondeterministic predicate as a (partial) row group filter, this fixes 
potentially incorrect results.
   
   ### How was this patch tested?
   
   Added a regression test in `DataSourceV2Suite` ("SPARK-58207: V2 filter 
pushdown skips non-deterministic filters") using 
`AdvancedDataSourceV2WithV2Filter`: it asserts that `rand() > 0.5` is not 
pushed to the source (only the deterministic `i > 3` is) and that the 
nondeterministic filter is retained as a post-scan filter. The test fails on 
master (the source receives `RAND(...) > 0.5`) and passes with this change.
   
   Also ran `DataSourceV2Suite` and `DataSourceV2EnhancedPartitionFilterSuite` 
(the latter exercises the iterative `PartitionPredicate` second pass) locally, 
both green.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Opus 4.8)
   


-- 
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