1
- use vortex_error:: VortexResult ;
1
+ use vortex_dtype:: { DType , StructDType } ;
2
+ use vortex_error:: { VortexExpect , VortexResult } ;
2
3
3
4
use super :: ChunkedArray ;
5
+ use crate :: arrays:: StructArray ;
4
6
use crate :: builders:: { ArrayBuilder , builder_with_capacity} ;
5
- use crate :: { Array as _, ArrayCanonicalImpl , Canonical } ;
7
+ use crate :: validity:: Validity ;
8
+ use crate :: { Array as _, ArrayCanonicalImpl , ArrayRef , Canonical } ;
6
9
7
10
impl ArrayCanonicalImpl for ChunkedArray {
8
11
fn _to_canonical ( & self ) -> VortexResult < Canonical > {
9
- let mut builder = builder_with_capacity ( self . dtype ( ) , self . len ( ) ) ;
10
- self . append_to_builder ( builder. as_mut ( ) ) ?;
11
- builder. finish ( ) . to_canonical ( )
12
+ match self . dtype ( ) {
13
+ DType :: Struct ( struct_dtype, _) => {
14
+ let struct_array = swizzle_struct_chunks (
15
+ self . chunks ( ) ,
16
+ Validity :: copy_from_array ( self ) ?,
17
+ struct_dtype,
18
+ ) ?;
19
+ Ok ( Canonical :: Struct ( struct_array) )
20
+ }
21
+ _ => {
22
+ let mut builder = builder_with_capacity ( self . dtype ( ) , self . len ( ) ) ;
23
+ self . append_to_builder ( builder. as_mut ( ) ) ?;
24
+ builder. finish ( ) . to_canonical ( )
25
+ }
26
+ }
12
27
}
13
28
14
29
fn _append_to_builder ( & self , builder : & mut dyn ArrayBuilder ) -> VortexResult < ( ) > {
@@ -19,6 +34,33 @@ impl ArrayCanonicalImpl for ChunkedArray {
19
34
}
20
35
}
21
36
37
+ /// Swizzle the pointers within a ChunkedArray of StructArrays to instead be a single
38
+ /// StructArray, where the Array for each Field is a ChunkedArray.
39
+ fn swizzle_struct_chunks (
40
+ chunks : & [ ArrayRef ] ,
41
+ validity : Validity ,
42
+ struct_dtype : & StructDType ,
43
+ ) -> VortexResult < StructArray > {
44
+ let len = chunks. iter ( ) . map ( |chunk| chunk. len ( ) ) . sum ( ) ;
45
+ let mut field_arrays = Vec :: new ( ) ;
46
+
47
+ for ( field_idx, field_dtype) in struct_dtype. fields ( ) . enumerate ( ) {
48
+ let field_chunks = chunks
49
+ . iter ( )
50
+ . map ( |c| {
51
+ c. as_struct_typed ( )
52
+ . vortex_expect ( "Chunk was not a StructArray" )
53
+ . maybe_null_field_by_idx ( field_idx)
54
+ . vortex_expect ( "Invalid chunked array" )
55
+ } )
56
+ . collect :: < Vec < _ > > ( ) ;
57
+ let field_array = ChunkedArray :: try_new ( field_chunks, field_dtype. clone ( ) ) ?;
58
+ field_arrays. push ( field_array. into_array ( ) ) ;
59
+ }
60
+
61
+ StructArray :: try_new ( struct_dtype. names ( ) . clone ( ) , field_arrays, len, validity)
62
+ }
63
+
22
64
#[ cfg( test) ]
23
65
mod tests {
24
66
use std:: sync:: Arc ;
0 commit comments