Repository navigation
fix(layout): apply struct nulls before evaluating field expressions - #10402
Closed
robert3005 wants to merge 1 commit into
Closed
robert3005 wants to merge 1 commit into
robert3005 wants to merge 1 commit into
Conversation
A nullable struct's fields store values even for rows where the struct is null. StructReader pushed filters straight down to the field readers, which know nothing about the parent's validity, so `x.value >= 0` matched rows where `x` itself was null. Projection masked the result afterwards instead of the input, which gave null instead of true for expressions such as `is_null(x.value)`, and pruning could use field statistics that include the hidden values. For nullable structs, read each field, apply the struct's validity, and only then evaluate the field-scoped expression, for both filters and projections. Skip statistics pruning for nullable structs. Non-nullable structs, including every file's root, keep full pushdown. Signed-off-by: Claude <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01E92wUoS3LaqWVJmmS7vKVq
Merging this PR will improve performance by 12.51%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | WallTime | bitpack_blocked_compress_avx2 |
7.6 µs | 6.8 µs | +12.51% |
Tip
Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.
Comparing rk/struct-filter-parent-validity (2133e00) with develop (c93ffa3)
Footnotes
-
534 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
robert3005
marked this pull request as draft
October 8, 2026 22:17
Contributor
Author
|
will wait for @myrrc pr |
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.
Summary
A nullable struct's fields store values even for rows where the struct itself is null. When reading a file,
StructReaderevaluated field expressions without taking that into account:x.value >= 0matched rows wherexis null. This is the bug behind the failing struct tests in fix(python): translate Polars struct field access #10194: a file scan returned 2 rows where Polars, and Vortex's own in-memory evaluation, return 1.is_null(x.value)gavenullinstead oftrueon rows wherexis null.Changes
All changes are in
vortex-layout/src/layouts/struct_/reader.rs, and only affect structs that are nullable (have a validity child):pack/merge) projection still masks each output field with the struct's validity, as before. That is how a nested nullable struct stays nullable when projected through its parent;vortex-file'swrite_nullable_nested_structcovers it.Non-nullable structs, including every file's root struct, keep the existing pushdown path unchanged. The cost is that predicates on fields of nullable nested structs are no longer pushed into the field readers and their statistics are no longer used for pruning. They are evaluated in memory after reading the field. Pushing down predicates that are provably false on null input would be a possible follow-up.
Tests
Added rstest cases to
struct_::reader::tests. The fixture is a nullable struct whose null row 0 still storesa = 7:a > 1,is_null(a), and the two-fielda > 5 OR b > 4respect the parent's nulls.is_null(a)returns[true, false, false].All four fail on
developand pass with this change.Checks run
cargo clippy -p vortex-layout --all-targets --all-features -- -D warnings: clean.cargo +nightly-2026-09-10 fmt -p vortex-layout.cargo nextest run -p vortex-layout -p vortex-file -p vortex-datafusion --all-features: 813 passed.-p vortex-scan: passed too.develop.🤖 Generated with Claude Code
https://claude.ai/code/session_01E92wUoS3LaqWVJmmS7vKVq
Generated by Claude Code