@@ -19,11 +19,13 @@ use crate::arrays::FixedSizeListArray;
1919use crate :: arrays:: ListViewArray ;
2020use crate :: arrays:: PrimitiveArray ;
2121use crate :: arrays:: StructArray ;
22+ use crate :: arrays:: UnionArray ;
2223use crate :: arrays:: VariantArray ;
2324use crate :: arrays:: chunked:: ChunkedArrayExt ;
2425use crate :: arrays:: fixed_size_list:: FixedSizeListArrayExt ;
2526use crate :: arrays:: listview:: ListViewArrayExt ;
2627use crate :: arrays:: listview:: ListViewRebuildMode ;
28+ use crate :: arrays:: union:: UnionArrayExt ;
2729use crate :: arrays:: variant:: VariantArrayExt ;
2830use crate :: builders:: builder_with_capacity_in;
2931use crate :: builtins:: ArrayBuiltins ;
@@ -54,6 +56,7 @@ pub(super) fn _canonicalize(
5456 let struct_array = pack_struct_chunks ( owned_chunks, ctx) ?;
5557 Canonical :: Struct ( struct_array)
5658 }
59+ DType :: Union ( ..) => Canonical :: Union ( pack_union_chunks ( owned_chunks, ctx) ?) ,
5760 DType :: List ( elem_dtype, _) => Canonical :: List ( swizzle_list_chunks (
5861 & owned_chunks,
5962 array. array ( ) . validity ( ) ?,
@@ -89,6 +92,47 @@ fn pack_struct_chunks(chunks: Vec<ArrayRef>, ctx: &mut ExecutionCtx) -> VortexRe
8992 . process_results ( |iter| StructArray :: try_concat ( iter) ) ?
9093}
9194
95+ /// Packs sparse union chunks into one union with chunked type IDs and sparse children.
96+ fn pack_union_chunks ( chunks : Vec < ArrayRef > , ctx : & mut ExecutionCtx ) -> VortexResult < UnionArray > {
97+ let union_chunks = chunks
98+ . into_iter ( )
99+ . map ( |chunk| chunk. execute :: < UnionArray > ( ctx) )
100+ . collect :: < VortexResult < Vec < _ > > > ( ) ?;
101+ let variants = union_chunks[ 0 ] . variants ( ) . clone ( ) ;
102+ let type_ids = ChunkedArray :: try_new (
103+ union_chunks
104+ . iter ( )
105+ . map ( |chunk| chunk. type_ids ( ) . clone ( ) )
106+ . collect ( ) ,
107+ DType :: Primitive ( PType :: I8 , Nullability :: NonNullable ) ,
108+ ) ?
109+ . into_array ( ) ;
110+ let children = ( 0 ..variants. len ( ) )
111+ . map ( |index| {
112+ let dtype = variants
113+ . variant_by_index ( index)
114+ . vortex_expect ( "variant index must have a dtype" ) ;
115+ ChunkedArray :: try_new (
116+ union_chunks
117+ . iter ( )
118+ . map ( |chunk| {
119+ chunk
120+ . child ( index)
121+ . vortex_expect ( "variant index must have a sparse child" )
122+ . clone ( )
123+ } )
124+ . collect ( ) ,
125+ dtype,
126+ )
127+ . map ( IntoArray :: into_array)
128+ } )
129+ . collect :: < VortexResult < Vec < _ > > > ( ) ?;
130+
131+ // SAFETY: Every component was taken from validated UnionArrays with the same dtype and
132+ // chunked along identical row boundaries.
133+ Ok ( unsafe { UnionArray :: new_unchecked ( type_ids, variants, children) } )
134+ }
135+
92136/// Packs many [`VariantArray`]s into one [`VariantArray`] with chunked children.
93137///
94138/// The caller guarantees there are at least 2 chunks.
0 commit comments