akar_common/
data_chunk.rs1use crate::selection::SelectionVector;
2use crate::types::{PhysicalTypeID, Value};
3use arrow::array::{ArrayRef, AsArray};
4use arrow::compute::take;
5use arrow::datatypes::*;
6
7#[derive(Debug, Clone)]
26pub struct DataChunk {
27 pub fields: Vec<ArrayRef>,
28 pub field_types: Vec<PhysicalTypeID>,
29 pub size: usize,
30 pub field_names: Vec<String>,
31 pub sel_vector: Option<SelectionVector>,
36}
37
38pub fn resize_chunk(chunk: &mut DataChunk, new_size: usize) {
40 chunk.size = new_size;
41 for field in &mut chunk.fields {
42 if new_size <= field.len() {
43 *field = field.slice(0, new_size);
44 }
45 }
46}
47
48impl DataChunk {
49 pub fn new(fields: Vec<ArrayRef>, field_types: Vec<PhysicalTypeID>) -> Self {
54 let size = fields.first().map(|f| f.len()).unwrap_or(0);
55 Self {
56 fields,
57 field_types,
58 size,
59 field_names: vec![],
60 sel_vector: None,
61 }
62 }
63
64 pub fn from_legacy(legacy_fields: Vec<crate::vector::ValueVector>) -> Self {
66 let field_types = legacy_fields.iter().map(|f| f.physical_type()).collect();
67 let arrow_fields = legacy_fields
68 .iter()
69 .map(|f| crate::arrow_vector::ArrowVector::from_legacy(f).array.clone())
70 .collect();
71 Self::new(arrow_fields, field_types)
72 }
73
74 pub fn with_names(mut self, names: Vec<String>) -> Self {
76 self.field_names = names;
77 self
78 }
79
80 pub fn with_sel(mut self, sel: SelectionVector) -> Self {
82 self.sel_vector = Some(sel);
83 self
84 }
85
86 #[inline(always)]
88 pub fn field(&self, idx: usize) -> &ArrayRef {
89 &self.fields[idx]
90 }
91
92 #[inline(always)]
94 pub fn num_fields(&self) -> usize {
95 self.fields.len()
96 }
97
98 #[inline(always)]
100 pub fn resize(&mut self, new_size: usize) {
101 resize_chunk(self, new_size);
102 }
103
104 #[inline(always)]
106 pub fn active_rows(&self) -> usize {
107 self.sel_vector.as_ref().map_or(self.size, |s| s.size)
108 }
109
110 pub fn iter_rows(&self) -> RowIter<'_> {
114 RowIter {
115 sel: self.sel_vector.as_ref(),
116 size: self.size,
117 pos: 0,
118 }
119 }
120
121 pub fn materialize(&mut self) {
125 let sel = match self.sel_vector.take() {
126 Some(s) => s,
127 None => return,
128 };
129 if sel.size == self.size {
130 return;
131 }
132 let indices = arrow::array::UInt32Array::from_iter_values(sel.indices[..sel.size].iter().copied());
133
134 for field in &mut self.fields {
135 *field = take(field.as_ref(), &indices, None).unwrap();
136 }
137 self.size = sel.size;
138 }
139
140 #[inline(always)]
142 pub fn is_null(&self, field_idx: usize, row_idx: usize) -> bool {
143 self.fields[field_idx].is_null(row_idx)
144 }
145
146 #[inline]
151 pub fn get_i64(&self, field_idx: usize, row_idx: usize) -> Option<i64> {
152 if self.is_null(field_idx, row_idx) {
153 return None;
154 }
155 if self.fields[field_idx].data_type() != &DataType::Int64 {
156 return None;
157 }
158 let arr = self.fields[field_idx].as_primitive::<Int64Type>();
159 Some(arr.value(row_idx))
160 }
161
162 #[inline]
164 pub fn get_u64(&self, field_idx: usize, row_idx: usize) -> Option<u64> {
165 if self.is_null(field_idx, row_idx) {
166 return None;
167 }
168 if self.fields[field_idx].data_type() != &DataType::UInt64 {
169 return None;
170 }
171 let arr = self.fields[field_idx].as_primitive::<UInt64Type>();
172 Some(arr.value(row_idx))
173 }
174
175 #[inline]
177 pub fn get_i32(&self, field_idx: usize, row_idx: usize) -> Option<i32> {
178 if self.is_null(field_idx, row_idx) {
179 return None;
180 }
181 let arr = self.fields[field_idx].as_primitive::<Int32Type>();
182 Some(arr.value(row_idx))
183 }
184
185 #[inline]
187 pub fn get_f64(&self, field_idx: usize, row_idx: usize) -> Option<f64> {
188 if self.is_null(field_idx, row_idx) {
189 return None;
190 }
191 let arr = self.fields[field_idx].as_primitive::<Float64Type>();
192 Some(arr.value(row_idx))
193 }
194
195 #[inline]
197 pub fn get_f32(&self, field_idx: usize, row_idx: usize) -> Option<f32> {
198 if self.is_null(field_idx, row_idx) {
199 return None;
200 }
201 let arr = self.fields[field_idx].as_primitive::<Float32Type>();
202 Some(arr.value(row_idx))
203 }
204
205 #[inline]
207 pub fn get_bool(&self, field_idx: usize, row_idx: usize) -> Option<bool> {
208 if self.is_null(field_idx, row_idx) {
209 return None;
210 }
211 let arr = self.fields[field_idx].as_boolean();
212 Some(arr.value(row_idx))
213 }
214
215 #[inline]
217 pub fn get_string(&self, field_idx: usize, row_idx: usize) -> Option<&str> {
218 if self.is_null(field_idx, row_idx) {
219 return None;
220 }
221 let arr = self.fields[field_idx].as_string::<i32>();
222 Some(arr.value(row_idx))
223 }
224
225 pub fn get_value(&self, field_idx: usize, row_idx: usize) -> Option<Value> {
230 if self.is_null(field_idx, row_idx) {
231 return None;
232 }
233 match self.field_types[field_idx] {
234 PhysicalTypeID::Int64 => self.get_i64(field_idx, row_idx).map(Value::Int64),
235 PhysicalTypeID::UInt64 => self.get_u64(field_idx, row_idx).map(Value::UInt64),
236 PhysicalTypeID::Int32 => self.get_i32(field_idx, row_idx).map(Value::Int32),
237 PhysicalTypeID::Double => self.get_f64(field_idx, row_idx).map(Value::Double),
238 PhysicalTypeID::Float => self.get_f32(field_idx, row_idx).map(Value::Float),
239 PhysicalTypeID::Bool => self.get_bool(field_idx, row_idx).map(Value::Bool),
240 PhysicalTypeID::String => self
241 .get_string(field_idx, row_idx)
242 .map(|s| Value::String(s.to_string())),
243 PhysicalTypeID::List | PhysicalTypeID::Array | PhysicalTypeID::Struct => {
244 crate::arrow_vector::convert_arrow_scalar(&self.fields[field_idx], row_idx)
245 }
246 _ => None, }
248 }
249}
250
251pub struct RowIter<'a> {
256 sel: Option<&'a SelectionVector>,
257 size: usize,
258 pos: usize,
259}
260
261impl<'a> Iterator for RowIter<'a> {
262 type Item = usize;
263
264 fn next(&mut self) -> Option<Self::Item> {
265 if let Some(sel) = self.sel {
266 if self.pos < sel.size {
267 let idx = sel.indices[self.pos] as usize;
268 self.pos += 1;
269 Some(idx)
270 } else {
271 None
272 }
273 } else {
274 if self.pos < self.size {
275 let idx = self.pos;
276 self.pos += 1;
277 Some(idx)
278 } else {
279 None
280 }
281 }
282 }
283
284 fn size_hint(&self) -> (usize, Option<usize>) {
285 let remaining = if let Some(sel) = self.sel {
286 sel.size.saturating_sub(self.pos)
287 } else {
288 self.size.saturating_sub(self.pos)
289 };
290 (remaining, Some(remaining))
291 }
292}
293
294impl<'a> ExactSizeIterator for RowIter<'a> {}