Add special case in validate_struct_compatibility for empty structs - #25023
Conversation
b14c880 to
483dd11
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #25023 +/- ##
==========================================
+ Coverage 81.70% 81.72% +0.02%
==========================================
Files 1127 1127
Lines 416001 416395 +394
Branches 416001 416395 +394
==========================================
+ Hits 339902 340312 +410
+ Misses 56125 56091 -34
- Partials 19974 19992 +18 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…mpatible with itself
483dd11 to
96e2e94
Compare
kumarUjjawal
left a comment
There was a problem hiding this comment.
Thank you @pepijnve for the fix. I left a comment.
Also The documentation at [nested_struct.rs line 45](
) is no longer accurate. It says structs without overlapping field names are rejected, but this change allows an empty source struct to cast to an empty or fully nullable target struct. Could we update this sentence to document the empty source exception?| } | ||
|
|
||
| #[test] | ||
| fn test_validate_struct_compatibility_empty_source_and_target() { |
There was a problem hiding this comment.
This test only verifies validation. After validation succeeds, cast_struct_column still calls StructArray::try_new with empty fields and arrays, which Arrow rejects because it cannot infer the row count. I reproduced this with a two row StructArray::new_empty_fields(2, None).
Please use try_new_with_length or new_empty_fields and add a cast_column regression that verifies the output length and null validity. Otherwise, the reported Iceberg query moves past planning but still fails during execution.
There was a problem hiding this comment.
Thanks for catching this. I had fixed the validation, then hit the arrow-rs error in the Avro decoder and didn't think of checking the cast implementation itself 🤦♂️
I adjusted the cast implementation and added tests covering the change.
I reviewed the documentation and I'm now wondering if this function should actually be even more flexible. It states
but then requires at least one overlapping field by name. Should we just drop the overlap check and let the nullability check that comes after it deal with the case where mapping is not possible instead? |
I think it was introduced in PR #19955 and was DataFusion 53 breaking change because unrelated structs could otherwise silently lose data. For example, casting {left: 1} to {alpha: INT NULL} would discard left and produce {alpha: NULL}. The nullability check only protects nonnullable target fields, so it cannot replace the overlap check. The empty source case is different because there are no source fields to discard. I suggest keeping the current exception and updating the documentation around nested_struct.rs lines 39 to 45 to say that a nonempty source requires at least one overlapping field name, while an empty source can cast to an empty or fully nullable target. |
Thanks for the pointer to the PR. The comment made by @adriangb that this matches DuckDB behaviour makes sense, and as you said, coming from an empty struct there's no information to lose anyway. I'll have a go at revising the doc comment. |
|
I've updated the documentation a bit and removed the duplication between the validation and cast functions. |
kumarUjjawal
left a comment
There was a problem hiding this comment.
Thank you @pepijnve
Head branch was pushed to by a user without write access
5008a2a to
4a370e1
Compare
|
Clippy warning fixed. |
Which issue does this PR close?
Rationale for this change
nested_struct::validate_struct_compatibilitychecks for at least one common field between the source and target field sets. This does not take into account that the source field set might be empty. This can cause issue during query planning.For instance, when querying an Iceberg table's manifest with no partitioning information the following error is produced:
What changes are included in this PR?
source_fields.is_empty()What is the testing strategy for this PR?
Are there any user-facing changes?
No