[SPARK-58207][SQL][FOLLOWUP] Skip runtime filter pushdown for nondeterministic filters - #57760
Open
peter-toth wants to merge 2 commits into
Open
Conversation
…rministic filters DataSourceV2Strategy no longer routes a non-deterministic post-scan filter into BatchScanExec.runtimeFilters, so it is not pushed to a SupportsRuntimeV2Filtering scan at runtime. apache#57357 guarded only PushDownUtils.pushFilters (pushdown at query compilation); the runtime path had no determinism guard, and since a scalar subquery runtime filter also stays in postScanFilters, the predicate was always evaluated twice with different results.
- Cite CleanupDynamicPruningFilters as the reason dynamicFilters needs no determinism check (a non-deterministic DynamicPruningSubquery is already rewritten to TrueLiteral before planning), rather than the weaker "not duplicated" argument. - Document the caller contract on PushDownUtils.pushRuntimeFilters, since the invariant is now enforced two files away in DataSourceV2Strategy. - Soften "would disagree" to "may disagree": the source is free to ignore a pushed runtime filter.
uros-b
approved these changes
Aug 4, 2026
Member
|
Thank you @peter-toth! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
Follow-up to #57357.
DataSourceV2Strategyno longer routes a non-deterministic post-scan filter intoBatchScanExec.runtimeFilters, so such a filter is not pushed to aSupportsRuntimeV2Filteringscan at runtime. The migration guide entry added by #57357 is widened to cover the runtime path.#57357 guarded the
SupportsPushDownV2Filtersbranch ofPushDownUtils.pushFilters, i.e. pushdown at query compilation. It did not touch the runtime filter path:DataSourceV2Strategyroutes scalar subquery filters on runtime-filterable columns intoruntimeFilters(SPARK-56467), andPushDownUtils.pushRuntimeFilterstranslates them withDataSourceV2Strategy.translateScalarSubqueryFilterV2, which has no determinism guard.Since #57357 shipped in 4.3 and this completes it, this should be merged to
branch-4.3as well asmasterandbranch-4.xso the widened migration-guide bullet ("Since Spark 4.3") is accurate and 4.3 carries the whole fix. This is a correctness fix rather than a new feature, and the cherry-pick is clean on both branches (verified locally).Why are the changes needed?
V2ExpressionBuildertranslatesRand, so a non-deterministic runtime filter reaches the data source. On master, against aSupportsRuntimeV2Filteringin-memory table:This is the problem #57357 describes, and the runtime path is more exposed to it than the compilation path. A scalar subquery runtime filter is deliberately kept in
postScanFiltersas well ("These filters stay in postScanFilters for correctness"), so Spark always re-evaluates it above the scan while the source is also free to prune on it. When the source does, the two evaluations ofrand()disagree, and a partition the source dropped is gone -- rows that Spark's evaluation would have kept cannot be recovered.Gating the routing rather than the translation keeps the non-deterministic filter out of
runtimeFiltersentirely, so it also stays out ofBatchScanExec'sequals/doCanonicalizeand out ofEXPLAIN, and nofilter()+planInputPartitions()round is wasted. Dynamic partition pruning filters need no such check: aDynamicPruningSubqueryover a non-deterministic filtering plan is itself non-deterministic (PlanExpression.deterministicfolds inplan.deterministic), so theFilterabove the scan failsNodeWithOnlyDeterministicProjectAndFilterandCleanupDynamicPruningFiltershas already rewritten it toTrueLiteralbefore planning.Does this PR introduce any user-facing change?
Yes, in unreleased 4.3, extending what #57357 already documented. Data sources implementing
SupportsRuntimeV2Filteringno longer receive non-deterministic runtime filters throughfilter. The filter is still evaluated by Spark after the scan, as it already was, so query results do not change for a source that ignored the pushed predicate; a source that pruned on it returns more rows than before, which is the point of the fix. The migration guide entry is updated.How was this patch tested?
Added
SPARK-58207: non-deterministic scalar subquery filters are not pushed into runtimeFilterstoDataSourceV2SQLSuiteV2Filter, next to the SPARK-56467 test it mirrors. It fails on master and passes with this change; the assertion that discriminates isruntimeFilters.isEmpty(on masterruntimeFiltersholds(part = subquery) OR (rand(...) < 0.5)). The other two assertions -- no partition pruned, filter still evaluated above the scan -- hold on master too and are there as sanity checks, not as evidence:InMemoryV2FilterBatchScan.filteracts only on a top-level=/INpredicate and ignores theOR, so no in-tree fixture prunes on a non-deterministic predicate today.Ran
DataSourceV2SQLSuiteV2Filter,DataSourceV2EnhancedRuntimePartitionFilterSuite(iterativePartitionPredicatesecond pass) andDataSourceV2Suitelocally, 243 tests green, plusdev/lint-scala.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 5)