Repository navigation
Conversation
PruneColumns.struct() added the original, unpruned field whenever the field id was selected. Parent struct ids are selected whenever any descendant is projected, so a deep leaf projection widened the read schema back to the full intermediate struct. Add the pruned field instead, and accumulate hasChange so a fully projected later sibling cannot reset pruning recorded by an earlier one. Co-authored-by: Ruijing Li <ruijingl@netflix.com> Generated-by: Claude Code (Claude Opus 5.5)
ff2ce6c to
e21a6ce
Compare
Generated-by: Claude Code (Claude Opus 5.5)
|
Thanks @jzhuge , very nice find! I just have a few minor comments. |
Generated-by: Claude Code (Claude Opus 5.5)
|
+1, LGTM! |
|
Can you follow the guidance in AGENTS.md for AI authored PRs? There is a disclosure block and some other rules. (Also one note for other reviewers, typically adding so many tests for a small change is discouraged, but in this case I feel it is worthwhile, given the nature of the change.) |
|
This PR should address an unresolved concern raised in #12634 by @rdblue . My thought about the concern is that if, say, a partial struct is passed into the struct prune method, then it is safe to assume the intent was a partial struct rather than the full struct. This is consistent with If that is deemed acceptable, then at the very least we should add a comment similar to the one for |
FrancisGodinho
left a comment
There was a problem hiding this comment.
lgtm after resolving the rest of the comments
Address review feedback: document in PruneColumns and ParquetSchemaUtil.pruneColumns that a partially projected struct is intentional and kept to its projected subtree, resolving the concern raised in apache#12634, and rename the map-value test whose name overstated its nesting depth. Generated-by: Claude Code (Claude Opus 5.5)
|
AI disclosure updated per AGENTS.md. On the #12634 concern: added javadoc on |
PruneColumns.struct()adds the original, unpruned Parquet field whenever the field's id is inselectedIds. A parent struct's id is inselectedIdswhenever any of its descendants is projected, so projecting one leaf of a deeply nested struct widens the read schema back to the full intermediate struct.This adds the pruned field instead. It also accumulates
hasChange(|=), so a fully projected sibling visited later cannot reset pruning recorded by an earlier sibling at the same level.Example: for
l1 struct<l2 struct<x, l3 struct<leaf, big>>>, projectingl1.l2.l3.leafpreviously read all ofl2. With this change it reads onlyl1.l2.l3.leaf. Whole-struct and top-level projections produce the same read schema as before. In our environment, reading a single deep leaf from a ~17 GB table took about 8x the scan task time of an id-only read, close to reading the whole parent struct.Notes for reviewers:
field == originalFieldat every level and the old path is kept.list()andmap()are unchanged. Structs inside list elements and map values prune correctly oncestruct()returns the pruned field.else if (field != null)branch now adds the pruned field instead of the original. This only matters for files where some fields have no ids. It should be more correct, but this is the area where review would help most.This revives #12634 and #14744, which were closed as stale, and addresses #11332.
Tests: 6 new tests in
TestPruneColumns. 4 fail onmainand pass with this change (testDeeplyNestedStructProjection,testDeeplyNestedStructMixed,testDeeplyNestedStructInsideList,testDeeplyNestedStructPartiallyProjectedBeforeFullyProjected). 2 pin unchanged behavior (testDeeplyNestedStructWhole,testNestedStructInsideMap)../gradlew :iceberg-parquet:checkpasses.AI Disclosure