sdf-jkl commented on code in PR #10313:
URL: https://github.com/apache/arrow-rs/pull/10313#discussion_r3731631478


##########
parquet-variant-compute/src/variant_to_arrow.rs:
##########
@@ -661,6 +674,216 @@ impl<'a> StructVariantToArrowRowBuilder<'a> {
     }
 }
 
+/// Builder for converting variant values into a [`UnionArray`].
+///
+/// Each value is dispatched to the union field that most exactly represents 
its runtime type
+/// (see [`union_child_rank`]), with ties broken by declaration order. Unions 
have no top-level
+/// null buffer, so null rows -- and, in safe mode, values no field can 
represent -- become a
+/// null in the [`DataType::Null`] child if the union declares one, otherwise 
in the first child.
+pub(crate) struct UnionVariantToArrowRowBuilder<'a> {
+    fields: &'a UnionFields,
+    mode: UnionMode,
+    children: Vec<UnionChildBuilder<'a>>,
+    type_ids: Vec<i8>,
+    /// Dense mode only
+    offsets: Vec<i32>,
+    null_child: usize,
+    cast_options: &'a CastOptions<'a>,
+}
+
+struct UnionChildBuilder<'a> {
+    type_id: i8,
+    builder: VariantToArrowRowBuilder<'a>,
+    len: i32,
+}
+
+impl<'a> UnionVariantToArrowRowBuilder<'a> {
+    fn try_new(
+        fields: &'a UnionFields,
+        mode: UnionMode,
+        cast_options: &'a CastOptions<'a>,
+        capacity: usize,
+    ) -> Result<Self> {
+        // null rows need a child to land in
+        if fields.is_empty() {
+            return Err(ArrowError::InvalidArgumentError(
+                "Casting Variant to a union requires at least one union 
field".to_string(),
+            ));
+        }
+        let mut children = Vec::with_capacity(fields.len());
+        for (type_id, field) in fields.iter() {
+            children.push(UnionChildBuilder {
+                type_id,
+                builder: make_typed_variant_to_arrow_row_builder(
+                    field.data_type(),
+                    cast_options,
+                    capacity,
+                )?,
+                len: 0,
+            });
+        }
+        let null_child = fields
+            .iter()
+            .position(|(_, field)| field.data_type() == &DataType::Null)
+            .unwrap_or(0);

Review Comment:
   I checked the existing Arrow union policy. `UnionBuilder::append_null` 
intentionally writes nulls into child arrays, while `UnionBuilder::build` still 
creates those child `Field`s 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.
   
   
https://github.com/apache/arrow-rs/blob/e28fd0d0f1f45e5608928eb52af3b12ffe9fee2e/arrow-array/src/builder/union_builder.rs#L285-L317



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to