vortex_array/arrays/struct_/vtable/
operator.rs1use std::sync::Arc;
5
6use vortex_error::VortexResult;
7use vortex_vector::Vector;
8use vortex_vector::struct_::StructVector;
9
10use crate::ArrayRef;
11use crate::arrays::{StructArray, StructVTable};
12use crate::execution::{BatchKernelRef, BindCtx, kernel};
13use crate::vtable::{OperatorVTable, ValidityHelper};
14
15impl OperatorVTable<StructVTable> for StructVTable {
16 fn bind(
17 array: &StructArray,
18 selection: Option<&ArrayRef>,
19 ctx: &mut dyn BindCtx,
20 ) -> VortexResult<BatchKernelRef> {
21 let field_kernels: Vec<_> = array
23 .fields()
24 .iter()
25 .map(|field| ctx.bind(field, selection))
26 .collect::<VortexResult<_>>()?;
27 let validity = ctx.bind_validity(array.validity(), array.len(), selection)?;
28
29 Ok(kernel(move || {
30 let fields: Vec<Vector> = field_kernels
32 .into_iter()
33 .map(|k| k.execute())
34 .collect::<VortexResult<_>>()?;
35 let validity_mask = validity.execute()?;
36
37 Ok(StructVector::try_new(Arc::new(fields.into_boxed_slice()), validity_mask)?.into())
38 }))
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use vortex_dtype::{FieldNames, PTypeDowncast};
45 use vortex_mask::Mask;
46 use vortex_vector::VectorOps;
47
48 use crate::IntoArray;
49 use crate::arrays::{BoolArray, PrimitiveArray, StructArray};
50 use crate::validity::Validity;
51
52 #[test]
53 fn test_struct_operator_basic() {
54 let int_field = PrimitiveArray::from_iter([1i32, 2, 3, 4, 5]);
56 let bool_field = BoolArray::from_iter([true, false, true, false, true]);
57
58 let struct_array = StructArray::try_new(
59 FieldNames::from(["ints", "bools"]),
60 vec![int_field.into_array(), bool_field.into_array()],
61 5,
62 Validity::AllValid,
63 )
64 .unwrap();
65
66 let result = struct_array.execute().unwrap();
68 assert_eq!(result.len(), 5);
69
70 let struct_vector = result.as_struct();
72 let fields = struct_vector.fields();
73 assert_eq!(fields.len(), 2);
74
75 let int_vector = fields[0].as_primitive().clone().into_i32();
77 assert_eq!(int_vector.elements().as_slice(), &[1, 2, 3, 4, 5]);
78
79 let bool_vector = fields[1].as_bool();
81 let bool_values: Vec<bool> = (0..5).map(|i| bool_vector.bits().value(i)).collect();
82 assert_eq!(bool_values, vec![true, false, true, false, true]);
83 }
84
85 #[test]
86 fn test_struct_operator_with_mask() {
87 let int_field = PrimitiveArray::from_iter([10i32, 20, 30, 40, 50, 60]);
89 let bool_field = BoolArray::from_iter([true, false, true, false, true, false]);
90
91 let struct_array = StructArray::try_new(
92 FieldNames::from(["numbers", "flags"]),
93 vec![int_field.into_array(), bool_field.into_array()],
94 6,
95 Validity::AllValid,
96 )
97 .unwrap();
98
99 let selection = Mask::from_iter([true, false, true, false, true, false]);
101
102 let result = struct_array.execute_with_selection(&selection).unwrap();
104
105 assert_eq!(result.len(), 3);
107
108 let struct_vector = result.as_struct();
110 let fields = struct_vector.fields();
111 assert_eq!(fields.len(), 2);
112
113 let int_vector = fields[0].as_primitive().clone().into_i32();
115 assert_eq!(int_vector.elements().as_slice(), &[10, 30, 50]);
116
117 let bool_vector = fields[1].as_bool();
119 let bool_values: Vec<bool> = (0..3).map(|i| bool_vector.bits().value(i)).collect();
120 assert_eq!(bool_values, vec![true, true, true]);
121 }
122
123 #[test]
124 fn test_struct_operator_null_handling() {
125 let int_field = PrimitiveArray::from_option_iter([
127 Some(100i32),
128 None,
129 Some(200),
130 Some(300),
131 None,
132 Some(400),
133 ]);
134
135 let bool_array = BoolArray::from_iter([true, false, true, false, true, false]);
137 let bool_validity = Validity::from_iter([true, true, false, true, true, false]);
138 let bool_field = BoolArray::from_bit_buffer(bool_array.bit_buffer().clone(), bool_validity);
139
140 let struct_validity = Validity::from_iter([true, false, true, true, false, true]);
142
143 let struct_array = StructArray::try_new(
144 FieldNames::from(["values", "flags"]),
145 vec![int_field.into_array(), bool_field.into_array()],
146 6,
147 struct_validity,
148 )
149 .unwrap();
150
151 let selection = Mask::from_iter([true, true, true, false, true, true]);
153
154 let result = struct_array.execute_with_selection(&selection).unwrap();
156
157 assert_eq!(result.len(), 5);
158
159 let struct_vector = result.as_struct();
161 let fields = struct_vector.fields();
162 assert_eq!(fields.len(), 2);
163
164 let int_vector = fields[0].as_primitive().clone().into_i32();
167 let int_values: Vec<Option<i32>> = (0..5).map(|i| int_vector.get(i).copied()).collect();
168 assert_eq!(
169 int_values,
170 vec![Some(100), None, Some(200), None, Some(400)]
171 );
172
173 let bool_vector = fields[1].as_bool();
176 let bool_values: Vec<bool> = (0..5).map(|i| bool_vector.bits().value(i)).collect();
177 assert_eq!(bool_values, vec![true, false, true, true, false]);
178
179 let validity_mask = struct_vector.validity();
183 let struct_validity_values: Vec<bool> = (0..5).map(|i| validity_mask.value(i)).collect();
184 assert_eq!(struct_validity_values, vec![true, false, true, false, true]);
185 }
186}