[BugFix] Avoid rewriting inside array_map lambda when pulling scan predicates up (backport #76380)#76396
Merged
Merged
Conversation
23 tasks
trueeyu
approved these changes
Jul 15, 2026
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.
Why I'm doing:
A query using array_map with a lambda whose body contains a constant IN list crashes the BE (SIGSEGV) when enable_predicate_expr_reuse is on (the default). Minimal repro:
12: cast is the outer SELECT CAST(1 AS BIGINT) output column. It is a valid column at the top of the SELECT node, but here it sits inside the lambda body, where only lambda arguments (<slot 10>) and captured columns exist — slot 12
is not in the lambda's local chunk.
Root cause: PullUpScanPredicateRule.replaceScalarOperator recursively rewrites every sub-expression of a pulled-up predicate to reuse scan projection columns, with no lambda boundary. When the outer query also selects a constant
(CAST(1 AS BIGINT)), that constant becomes a scan projection column (slot), and the structurally-identical constant sitting inside the array_map lambda's IN list gets rewritten into a ColumnRef of that column — producing ... IN
(, 2).
A lambda body is evaluated in a local chunk (only lambda arguments and captured columns exist), and the constant IN-predicate is built as VectorizedInConstPredicate on the BE, whose open() evaluates its elements against a null
chunk. Dereferencing that ColumnRef against the null chunk crashes the BE (Chunk::get_column_by_slot_id on nullptr).
What I'm doing:
Do not rewrite anything inside a LambdaFunctionOperator body in PullUpScanPredicateRule.replaceScalarOperator. Reuse of scan projection columns is only valid at the top level of the predicate, where the column exists in the
operator's input chunk; inside a lambda only lambda arguments and captured columns are in scope. This mirrors SubfieldCollector#visitLambdaFunctionOperator, which already never descends into lambdas. Lambda-internal
common-subexpression reuse continues to be handled correctly by ScalarOperatorsReuseRule, which is lambda-aware.
What type of PR is this:
Does this PR entail a change in behavior?
If yes, please specify the type of change:
Checklist:
Bugfix cherry-pick branch check:
This is an automatic backport of pull request #76380 done by [Mergify](https://mergify.com).