[Variant] add variant_to_arrow union builder - #10313
Conversation
Casting Variant to dense or sparse Union dispatches each value to the union field that most exactly represents its runtime type (lossless widening allowed, declaration order breaks ties). Null rows land in a Null-typed child if declared, otherwise the first child, since unions have no top-level null buffer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
variant_to_arrow union buildervariant_to_arrow union builder
Jefffrey
left a comment
There was a problem hiding this comment.
disclaimer: this is kinda my first time looking at variant code 😅
| let null_child = fields | ||
| .iter() | ||
| .position(|(_, field)| field.data_type() == &DataType::Null) | ||
| .unwrap_or(0); |
There was a problem hiding this comment.
do we need to consider nullability of the field?
There was a problem hiding this comment.
I checked the existing Arrow union policy. UnionBuilder::append_null intentionally writes nulls into child arrays, while UnionBuilder::build still creates those child Fields with nullable = false. UnionArray::try_new does not validate field nullability, and union nullness is derived from the selected child array. Therefore the fallback does not need to select a nullable-declared field.
arrow-rs/arrow-array/src/builder/union_builder.rs
Lines 285 to 317 in e28fd0d
There was a problem hiding this comment.
the builder thing is a known issue:
i guess its one of those things which is a bit messy in the codebase as is 🤔
|
Thanks @Jefffrey 🙏 This is not the most |
|
@klion26 please you take a look 🙏 |
|
thanks @sdf-jkl |
# Which issue does this PR close? <!-- We generally require a GitHub issue to be filed for all bug fixes and enhancements and this helps us generate change logs for our releases. You can link an issue to this PR using the GitHub syntax. --> The last type to be supported by `variant_to_arrow` cast. - Closes apache#8477. # Rationale for this change Check issue <!-- Why are you proposing this change? If this is already explained clearly in the issue then this section is not needed. Explaining clearly why changes are proposed helps reviewers understand your changes and offer better suggestions for fixes. --> # What changes are included in this PR? - Add `variant_to_arrow` union cast support + unit tests <!-- There is no need to duplicate the description in the issue here but it is sometimes worth providing a summary of the individual changes in this PR. --> # Are these changes tested? - Yes, unit tests <!-- We typically require tests for all PRs in order to: 1. Prevent the code from being accidentally broken by subsequent changes 2. Serve as another way to document the expected behavior of the code If tests are not included in your PR, please explain why (for example, are they covered by existing tests)? If this PR claims a performance improvement, please include evidence such as benchmark results. --> # Are there any user-facing changes? - Users can now cast Variant to Union type <!-- If there are user-facing changes then we may require documentation to be updated before approving the PR. If there are any breaking changes to public APIs, please call them out. --> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>
|
Thanks for pushing this forward. Sorry for the late reply, a little busy in the inter works the last days. I'll take a look at this and reply if I have any comments |
| /// type: 0 is the value's natural Arrow type, higher ranks are lossless widenings, and `None` | ||
| /// means the child cannot represent the value losslessly. Every pair admitted here must be | ||
| /// convertible by the corresponding row builder. | ||
| fn union_child_rank(value: &Variant<'_, '_>, data_type: &DataType) -> Option<u8> { |
There was a problem hiding this comment.
Here we use type-based info to determine which target the current variant should belong to. This seems incorrect
- Variant::Int64(1) can't convert to DataType::Int8, but this should valid when calling
variant_get - The logic in the current code (json -> variant, and variant spec), treats the exact number the same in Variant::Int64/Int32/Int16 etc(value has no strict type in variant) (like the
Equivalence Classin parquet variant spec)
There was a problem hiding this comment.
Maybe we can sort the field in the Union, and try the target column in the sorted order like we treat like the json-> variant(from_json.rs in parquet-variant-compute)
Which issue does this PR close?
The last type to be supported by
variant_to_arrowcast.Rationale for this change
Check issue
What changes are included in this PR?
variant_to_arrowunion cast support + unit testsAre these changes tested?
Are there any user-facing changes?