[SPARK-58428][SQL] Fix optimizer hang in DSv2 expression pushdown - #57974
Open
AbhinavBattu wants to merge 1 commit into
Open
[SPARK-58428][SQL] Fix optimizer hang in DSv2 expression pushdown#57974AbhinavBattu wants to merge 1 commit into
AbhinavBattu wants to merge 1 commit into
Conversation
`V2ExpressionBuilder.generateExpression` constant folds a foldable expression and recurses on the result, assuming it is now a literal. `ConstantFolding` returns the expression unchanged when its evaluation failed inside a conditional branch, so the recursion never makes progress. The call is in tail position, so this hangs instead of overflowing the stack. Only recurse when folding actually changed the expression.
uros-b
approved these changes
Aug 13, 2026
Member
|
Thank you @AbhinavBattu! Adding @gengliangwang to also take a look |
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?
V2ExpressionBuilder.generateExpressionhandles a context independent foldableexpression by constant folding it and recursing on the result, so that the folded
value is translated by the
Literalcase:That assumes constant folding returns a literal. It does not.
ConstantFoldingreturns an expression unchanged when it carries the
FAILED_TO_EVALUATEtag, whichis set when evaluation failed inside a conditional branch so that the error is not
raised at planning time for a branch that may never be reached. The recursive call
then re-enters the same case with the same expression and never makes progress.
Because the call is in tail position it loops instead of raising
StackOverflowError, so the symptom is a query that never returns.This PR recurses only when folding actually changed the expression.
This follows SPARK-50380, which made
ReorderAssociativeOperatorstop assuming thata foldable expression folds to a literal.
The guard is on the folding result rather than on the tag, so it also covers any
future case where
constantFoldingreturns its input unchanged.Why are the changes needed?
With default settings, a pushdown eligible query against a DSv2 source hangs when a
filter contains an expression that fails to evaluate inside a conditional branch:
Four conditions have to hold, which is why this was not hit earlier:
1 div 0throws while the planner folds itrather than raised
V2ExpressionBuilderis only used onthat path
spark.sql.optimizer.datasourceV2ExprFolding, which defaults to true and wasadded in 4.1.0
Setting
spark.sql.optimizer.datasourceV2ExprFoldingto false avoids the hang.Does this PR introduce any user-facing change?
Yes. A query of the shape above previously hung and now completes. Such an
expression is no longer translated, so the predicate is not pushed to the source and
is evaluated by Spark instead. Query results are unchanged.
How was this patch tested?
Added a test to
DataSourceV2StrategySuite, next to the existingdatasourceV2ExprFoldingtest. It buildscoalesce(c, 1 div 0) = 1, asserts thatconstant folding tagged the failing branch, and then asserts that translation
produces no V2 expression. The tag assertion is there so that the test cannot pass
for the wrong reason if the tagging behaviour changes.
Without this change the test does not terminate. The recursion is in tail position
and does not block, so it cannot be interrupted by a time limit, which is why the
test asserts the result instead of using
failAfter. This matches existing testsfor similar issues, for example "SPARK-48843: Prevent infinite loop with
BindParameters" in
ParametersSuite.Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)