1use crate::array::print_long_array;
19use crate::{Array, ArrayRef, RecordBatch, make_array, new_null_array};
20use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer};
21use arrow_data::{ArrayData, ArrayDataBuilder};
22use arrow_schema::{ArrowError, DataType, Field, FieldRef, Fields};
23use std::sync::Arc;
24use std::{any::Any, ops::Index};
25
26#[derive(Clone)]
77pub struct StructArray {
78 len: usize,
79 data_type: DataType,
80 nulls: Option<NullBuffer>,
81 fields: Vec<ArrayRef>,
82}
83
84impl StructArray {
85 pub fn new(fields: Fields, arrays: Vec<ArrayRef>, nulls: Option<NullBuffer>) -> Self {
91 Self::try_new(fields, arrays, nulls).unwrap()
92 }
93
94 pub fn try_new(
107 fields: Fields,
108 arrays: Vec<ArrayRef>,
109 nulls: Option<NullBuffer>,
110 ) -> Result<Self, ArrowError> {
111 let len = arrays.first().map(|x| x.len()).ok_or_else(||ArrowError::InvalidArgumentError("use StructArray::try_new_with_length or StructArray::new_empty_fields to create a struct array with no fields so that the length can be set correctly".to_string()))?;
112
113 Self::try_new_with_length(fields, arrays, nulls, len)
114 }
115
116 pub fn try_new_with_length(
128 fields: Fields,
129 arrays: Vec<ArrayRef>,
130 nulls: Option<NullBuffer>,
131 len: usize,
132 ) -> Result<Self, ArrowError> {
133 if fields.len() != arrays.len() {
134 return Err(ArrowError::InvalidArgumentError(format!(
135 "Incorrect number of arrays for StructArray fields, expected {} got {}",
136 fields.len(),
137 arrays.len()
138 )));
139 }
140
141 if let Some(n) = nulls.as_ref()
142 && n.len() != len
143 {
144 return Err(ArrowError::InvalidArgumentError(format!(
145 "Incorrect number of nulls for StructArray, expected {len} got {}",
146 n.len(),
147 )));
148 }
149
150 for (f, a) in fields.iter().zip(&arrays) {
151 if f.data_type() != a.data_type() {
152 return Err(ArrowError::InvalidArgumentError(format!(
153 "Incorrect datatype for StructArray field {:?}, expected {} got {}",
154 f.name(),
155 f.data_type(),
156 a.data_type()
157 )));
158 }
159
160 if a.len() != len {
161 return Err(ArrowError::InvalidArgumentError(format!(
162 "Incorrect array length for StructArray field {:?}, expected {} got {}",
163 f.name(),
164 len,
165 a.len()
166 )));
167 }
168
169 if !f.is_nullable()
170 && let Some(a) = a.logical_nulls()
171 && nulls.as_ref().is_none_or(|n| !n.contains(&a))
172 && a.null_count() > 0
173 {
174 return Err(ArrowError::InvalidArgumentError(format!(
175 "Found unmasked nulls for non-nullable StructArray field {:?}",
176 f.name()
177 )));
178 }
179 }
180
181 Ok(Self {
182 len,
183 data_type: DataType::Struct(fields),
184 nulls: nulls.filter(|n| n.null_count() > 0),
185 fields: arrays,
186 })
187 }
188
189 pub fn new_null(fields: Fields, len: usize) -> Self {
191 let arrays = fields
192 .iter()
193 .map(|f| new_null_array(f.data_type(), len))
194 .collect();
195
196 Self {
197 len,
198 data_type: DataType::Struct(fields),
199 nulls: Some(NullBuffer::new_null(len)),
200 fields: arrays,
201 }
202 }
203
204 pub unsafe fn new_unchecked(
214 fields: Fields,
215 arrays: Vec<ArrayRef>,
216 nulls: Option<NullBuffer>,
217 ) -> Self {
218 if cfg!(feature = "force_validate") {
219 return Self::new(fields, arrays, nulls);
220 }
221
222 let len = arrays.first().map(|x| x.len()).expect(
223 "cannot use StructArray::new_unchecked if there are no fields, length is unknown",
224 );
225 Self {
226 len,
227 data_type: DataType::Struct(fields),
228 nulls,
229 fields: arrays,
230 }
231 }
232
233 pub unsafe fn new_unchecked_with_length(
239 fields: Fields,
240 arrays: Vec<ArrayRef>,
241 nulls: Option<NullBuffer>,
242 len: usize,
243 ) -> Self {
244 if cfg!(feature = "force_validate") {
245 return Self::try_new_with_length(fields, arrays, nulls, len).unwrap();
246 }
247
248 Self {
249 len,
250 data_type: DataType::Struct(fields),
251 nulls,
252 fields: arrays,
253 }
254 }
255
256 pub fn new_empty_fields(len: usize, nulls: Option<NullBuffer>) -> Self {
262 if let Some(n) = &nulls {
263 assert_eq!(len, n.len())
264 }
265 Self {
266 len,
267 data_type: DataType::Struct(Fields::empty()),
268 fields: vec![],
269 nulls,
270 }
271 }
272
273 pub fn into_parts(self) -> (Fields, Vec<ArrayRef>, Option<NullBuffer>) {
275 let DataType::Struct(f) = self.data_type else {
276 unreachable!()
277 };
278 (f, self.fields, self.nulls)
279 }
280
281 pub fn column(&self, pos: usize) -> &ArrayRef {
286 &self.fields[pos]
287 }
288
289 pub fn num_columns(&self) -> usize {
291 self.fields.len()
292 }
293
294 pub fn columns(&self) -> &[ArrayRef] {
296 &self.fields
297 }
298
299 pub fn column_names(&self) -> Vec<&str> {
301 match self.data_type() {
302 DataType::Struct(fields) => fields
303 .iter()
304 .map(|f| f.name().as_str())
305 .collect::<Vec<&str>>(),
306 _ => unreachable!("Struct array's data type is not struct!"),
307 }
308 }
309
310 pub fn fields(&self) -> &Fields {
312 match self.data_type() {
313 DataType::Struct(f) => f,
314 _ => unreachable!(),
315 }
316 }
317
318 pub fn column_by_name(&self, column_name: &str) -> Option<&ArrayRef> {
324 self.fields()
325 .find(column_name)
326 .map(|(pos, _)| self.column(pos))
327 }
328
329 pub fn field(&self, pos: usize) -> &FieldRef {
331 &self.fields()[pos]
332 }
333
334 pub fn field_by_name(&self, field_name: &str) -> Option<&FieldRef> {
340 self.fields().find(field_name).map(|(_, field)| field)
341 }
342
343 pub fn slice(&self, offset: usize, len: usize) -> Self {
348 assert!(
349 offset.saturating_add(len) <= self.len,
350 "the length + offset of the sliced StructArray cannot exceed the existing length"
351 );
352
353 let fields = self.fields.iter().map(|a| a.slice(offset, len)).collect();
354
355 Self {
356 len,
357 data_type: self.data_type.clone(),
358 nulls: self.nulls.as_ref().map(|n| n.slice(offset, len)),
359 fields,
360 }
361 }
362
363 pub fn flatten(&self) -> (Fields, Vec<ArrayRef>) {
393 let schema_fields = self.fields();
394
395 let Some(struct_nulls) = &self.nulls else {
396 return (schema_fields.clone(), self.fields.clone());
397 };
398
399 let new_fields: Fields = schema_fields
400 .iter()
401 .map(|f| {
402 if f.is_nullable() {
403 Arc::clone(f)
404 } else {
405 Arc::new(f.as_ref().clone().with_nullable(true))
406 }
407 })
408 .collect::<Vec<_>>()
409 .into();
410
411 let new_columns = self
412 .fields
413 .iter()
414 .map(|child| {
415 let merged = NullBuffer::union(Some(struct_nulls), child.nulls());
416 let data = child.to_data().into_builder().nulls(merged);
419 make_array(unsafe { data.build_unchecked() })
420 })
421 .collect();
422
423 (new_fields, new_columns)
424 }
425}
426
427impl From<ArrayData> for StructArray {
428 fn from(data: ArrayData) -> Self {
429 let (data_type, len, nulls, offset, _buffers, child_data) = data.into_parts();
430
431 let parent_offset = offset;
432 let parent_len = len;
433
434 let fields = child_data
435 .into_iter()
436 .map(|cd| {
437 if parent_offset != 0 || parent_len != cd.len() {
438 make_array(cd.slice(parent_offset, parent_len))
439 } else {
440 make_array(cd)
441 }
442 })
443 .collect();
444
445 Self {
446 len,
447 data_type,
448 nulls,
449 fields,
450 }
451 }
452}
453
454impl From<StructArray> for ArrayData {
455 fn from(array: StructArray) -> Self {
456 let builder = ArrayDataBuilder::new(array.data_type)
457 .len(array.len)
458 .nulls(array.nulls)
459 .child_data(array.fields.iter().map(|x| x.to_data()).collect());
460
461 unsafe { builder.build_unchecked() }
462 }
463}
464
465impl TryFrom<Vec<(&str, ArrayRef)>> for StructArray {
466 type Error = ArrowError;
467
468 fn try_from(values: Vec<(&str, ArrayRef)>) -> Result<Self, ArrowError> {
470 let (fields, arrays): (Vec<_>, _) = values
471 .into_iter()
472 .map(|(name, array)| {
473 (
474 Field::new(name, array.data_type().clone(), array.is_nullable()),
475 array,
476 )
477 })
478 .unzip();
479
480 StructArray::try_new(fields.into(), arrays, None)
481 }
482}
483
484unsafe impl Array for StructArray {
486 fn as_any(&self) -> &dyn Any {
487 self
488 }
489
490 fn to_data(&self) -> ArrayData {
491 self.clone().into()
492 }
493
494 fn into_data(self) -> ArrayData {
495 self.into()
496 }
497
498 fn data_type(&self) -> &DataType {
499 &self.data_type
500 }
501
502 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
503 Arc::new(self.slice(offset, length))
504 }
505
506 fn len(&self) -> usize {
507 self.len
508 }
509
510 fn is_empty(&self) -> bool {
511 self.len == 0
512 }
513
514 fn shrink_to_fit(&mut self) {
515 if let Some(nulls) = &mut self.nulls {
516 nulls.shrink_to_fit();
517 }
518 self.fields.iter_mut().for_each(|n| n.shrink_to_fit());
519 }
520
521 fn offset(&self) -> usize {
522 0
523 }
524
525 fn nulls(&self) -> Option<&NullBuffer> {
526 self.nulls.as_ref()
527 }
528
529 fn logical_null_count(&self) -> usize {
530 self.null_count()
532 }
533
534 fn get_buffer_memory_size(&self) -> usize {
535 let mut size = self.fields.iter().map(|a| a.get_buffer_memory_size()).sum();
536 if let Some(n) = self.nulls.as_ref() {
537 size += n.buffer().capacity();
538 }
539 size
540 }
541
542 fn get_array_memory_size(&self) -> usize {
543 let mut size = self.fields.iter().map(|a| a.get_array_memory_size()).sum();
544 size += std::mem::size_of::<Self>();
545 if let Some(n) = self.nulls.as_ref() {
546 size += n.buffer().capacity();
547 }
548 size
549 }
550
551 #[cfg(feature = "pool")]
552 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
553 for field in &self.fields {
554 field.claim(pool);
555 }
556 if let Some(nulls) = &self.nulls {
557 nulls.claim(pool);
558 }
559 }
560}
561
562impl From<Vec<(FieldRef, ArrayRef)>> for StructArray {
563 fn from(v: Vec<(FieldRef, ArrayRef)>) -> Self {
564 let (fields, arrays): (Vec<_>, _) = v.into_iter().unzip();
565 StructArray::new(fields.into(), arrays, None)
566 }
567}
568
569impl std::fmt::Debug for StructArray {
570 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
571 writeln!(f, "StructArray")?;
572 writeln!(f, "-- validity:")?;
573 writeln!(f, "[")?;
574 print_long_array(self, f, &mut |_index, f| write!(f, "valid"))?;
575 writeln!(f, "]\n[")?;
576 for (child_index, name) in self.column_names().iter().enumerate() {
577 let column = self.column(child_index);
578 writeln!(
579 f,
580 "-- child {}: \"{}\" ({:?})",
581 child_index,
582 name,
583 column.data_type()
584 )?;
585 std::fmt::Debug::fmt(column, f)?;
586 writeln!(f)?;
587 }
588 write!(f, "]")
589 }
590}
591
592impl From<(Vec<(FieldRef, ArrayRef)>, Buffer)> for StructArray {
593 fn from(pair: (Vec<(FieldRef, ArrayRef)>, Buffer)) -> Self {
594 let len = pair.0.first().map(|x| x.1.len()).unwrap_or_default();
595 let (fields, arrays): (Vec<_>, Vec<_>) = pair.0.into_iter().unzip();
596 let nulls = NullBuffer::new(BooleanBuffer::new(pair.1, 0, len));
597 Self::new(fields.into(), arrays, Some(nulls))
598 }
599}
600
601impl From<RecordBatch> for StructArray {
602 fn from(value: RecordBatch) -> Self {
603 Self {
604 len: value.num_rows(),
605 data_type: DataType::Struct(value.schema().fields().clone()),
606 nulls: None,
607 fields: value.columns().to_vec(),
608 }
609 }
610}
611
612impl Index<&str> for StructArray {
613 type Output = ArrayRef;
614
615 fn index(&self, name: &str) -> &Self::Output {
625 self.column_by_name(name).unwrap()
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use super::*;
632
633 use crate::{
634 BooleanArray, Float32Array, Float64Array, Int32Array, Int64Array, StringArray,
635 cast::AsArray, types::Int32Type,
636 };
637 use arrow_buffer::ToByteSlice;
638
639 #[test]
640 fn test_struct_array_builder() {
641 let boolean_array = BooleanArray::from(vec![false, false, true, true]);
642 let int_array = Int64Array::from(vec![42, 28, 19, 31]);
643
644 let fields = vec![
645 Field::new("a", DataType::Boolean, false),
646 Field::new("b", DataType::Int64, false),
647 ];
648 let struct_array_data = ArrayData::builder(DataType::Struct(fields.into()))
649 .len(4)
650 .add_child_data(boolean_array.to_data())
651 .add_child_data(int_array.to_data())
652 .build()
653 .unwrap();
654 let struct_array = StructArray::from(struct_array_data);
655
656 assert_eq!(struct_array.column(0).as_ref(), &boolean_array);
657 assert_eq!(struct_array.column(1).as_ref(), &int_array);
658 }
659
660 #[test]
661 fn test_struct_array_from() {
662 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
663 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
664
665 let struct_array = StructArray::from(vec![
666 (
667 Arc::new(Field::new("b", DataType::Boolean, false)),
668 boolean.clone() as ArrayRef,
669 ),
670 (
671 Arc::new(Field::new("c", DataType::Int32, false)),
672 int.clone() as ArrayRef,
673 ),
674 ]);
675 assert_eq!(struct_array.column(0).as_ref(), boolean.as_ref());
676 assert_eq!(struct_array.column(1).as_ref(), int.as_ref());
677 assert_eq!(4, struct_array.len());
678 assert_eq!(0, struct_array.null_count());
679 assert_eq!(0, struct_array.offset());
680 }
681
682 #[test]
683 fn test_struct_array_from_data_with_offset_and_length() {
684 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
690 let int_field = Field::new("x", DataType::Int32, false);
691 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
692 let int_data = int_arr.to_data();
693 let case1 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
695 .len(3)
696 .offset(1)
697 .nulls(Some(struct_nulls))
698 .add_child_data(int_data.clone())
699 .build()
700 .unwrap();
701
702 let struct_nulls =
704 NullBuffer::new(BooleanBuffer::from(vec![true, true, true, false, true]).slice(1, 3));
705 let case2 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
706 .len(3)
707 .offset(1)
708 .nulls(Some(struct_nulls.clone()))
709 .add_child_data(int_data.clone())
710 .build()
711 .unwrap();
712
713 let offset_int_data = int_data.slice(1, 4);
715 let case3 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
716 .len(3)
717 .nulls(Some(struct_nulls))
718 .add_child_data(offset_int_data)
719 .build()
720 .unwrap();
721
722 let expected = StructArray::new(
723 Fields::from(vec![int_field.clone()]),
724 vec![Arc::new(int_arr)],
725 Some(NullBuffer::new(BooleanBuffer::from(vec![
726 true, true, true, false, true,
727 ]))),
728 )
729 .slice(1, 3);
730
731 for case in [case1, case2, case3] {
732 let struct_arr_from_data = StructArray::from(case);
733 assert_eq!(struct_arr_from_data, expected);
734 assert_eq!(struct_arr_from_data.column(0), expected.column(0));
735 }
736 }
737
738 #[test]
739 fn test_struct_array_data_slice() {
740 let x = Int32Array::from(vec![Some(0), Some(1), Some(2), Some(3), None, Some(5)]);
743 let struct_array = StructArray::new(
744 Fields::from(vec![Field::new("x", DataType::Int32, true)]),
745 vec![Arc::new(x.clone())],
746 Some(NullBuffer::from(vec![true, true, true, false, true, true])),
747 )
748 .into_data();
749 let sliced = struct_array.slice(1, 4);
750
751 let arr = make_array(sliced);
752 assert_eq!(
753 arr.as_struct().column(0).as_primitive::<Int32Type>(),
754 &x.slice(1, 4)
755 );
756
757 let x = Int32Array::from(vec![Some(0), Some(1), Some(2), Some(3), None, Some(5)]);
763 let y = Int32Array::from(vec![Some(5), Some(6), None, Some(8), Some(9), Some(10)]);
764 let struct_array = StructArray::new(
765 Fields::from(vec![
766 Field::new("x", DataType::Int32, true),
767 Field::new("y", DataType::Int32, true),
768 ]),
769 vec![Arc::new(x), Arc::new(y)],
770 Some(NullBuffer::from(vec![true, true, true, false, true, true])),
771 );
772 let struct_array = StructArray::new(
773 Fields::from(vec![Field::new(
774 "inner",
775 struct_array.data_type().clone(),
776 true,
777 )]),
778 vec![Arc::new(struct_array)],
779 Some(NullBuffer::from(vec![true, false, true, true, true, true])),
780 );
781
782 let cpp_sliced_array = make_array(
783 struct_array
784 .to_data()
785 .into_builder()
786 .offset(1)
787 .len(4)
788 .nulls(Some(NullBuffer::from(vec![false, true, true, true])))
789 .build()
790 .unwrap(),
791 );
792
793 assert_eq!(cpp_sliced_array.as_struct(), &struct_array.slice(1, 4));
794 }
795
796 #[test]
797 fn test_make_array_sliced_struct_data() {
798 let strings: ArrayRef = Arc::new(StringArray::from(vec![
801 Some("joe"),
802 None,
803 None,
804 Some("mark"),
805 Some("doe"),
806 ]));
807 let ints: ArrayRef = Arc::new(Int32Array::from(vec![
808 Some(1),
809 Some(2),
810 Some(3),
811 Some(4),
812 Some(5),
813 ]));
814
815 let array = StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())])
816 .unwrap()
817 .into_data()
818 .slice(1, 3);
819
820 let arr = make_array(array);
821 let expected = StructArray::try_from(vec![("f1", strings), ("f2", ints)])
822 .unwrap()
823 .slice(1, 3);
824 assert_eq!(arr.as_struct(), &expected);
825 }
826
827 #[test]
828 fn test_slice_struct_data_with_existing_offset() {
829 let x = Int32Array::from(vec![Some(0), Some(1), Some(2), Some(3), None, Some(5)]);
835 let struct_array = StructArray::new(
836 Fields::from(vec![Field::new("x", DataType::Int32, true)]),
837 vec![Arc::new(x.clone())],
838 Some(NullBuffer::from(vec![true, true, true, false, true, true])),
839 );
840
841 let offset_data = struct_array
842 .to_data()
843 .into_builder()
844 .offset(1)
845 .len(5)
846 .nulls(Some(NullBuffer::from(vec![true, true, false, true, true])))
847 .build()
848 .unwrap();
849
850 let sliced = offset_data.slice(1, 3);
851 assert_eq!(sliced.offset(), 0);
854 assert_eq!(sliced.len(), 3);
855 assert_eq!(sliced.child_data()[0].offset(), 2);
856 assert_eq!(sliced.child_data()[0].len(), 3);
857
858 let arr = make_array(sliced);
859 assert_eq!(
860 arr.as_struct().column(0).as_primitive::<Int32Type>(),
861 &x.slice(2, 3)
862 );
863 assert_eq!(arr.as_struct(), &struct_array.slice(2, 3));
864 }
865
866 #[test]
867 fn test_struct_array_from_data_with_offset_and_length_error() {
868 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
869 let int_field = Field::new("x", DataType::Int32, false);
870 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
871 let int_data = int_arr.to_data();
872 let err = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
874 .len(3)
875 .offset(3)
876 .nulls(Some(struct_nulls))
877 .add_child_data(int_data)
878 .build()
879 .unwrap_err()
880 .to_string();
881
882 assert!(err.contains(
883 "child array #0 for field x has length smaller than expected for struct array (5 < 6)"
884 ));
885 }
886
887 #[test]
889 fn test_struct_array_index_access() {
890 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
891 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
892
893 let struct_array = StructArray::from(vec![
894 (
895 Arc::new(Field::new("b", DataType::Boolean, false)),
896 boolean.clone() as ArrayRef,
897 ),
898 (
899 Arc::new(Field::new("c", DataType::Int32, false)),
900 int.clone() as ArrayRef,
901 ),
902 ]);
903 assert_eq!(struct_array["b"].as_ref(), boolean.as_ref());
904 assert_eq!(struct_array["c"].as_ref(), int.as_ref());
905 }
906
907 #[test]
908 fn test_struct_array_field_access() {
909 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
910 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
911
912 let b_field = Arc::new(Field::new("b", DataType::Boolean, false));
913 let c_field = Arc::new(Field::new("c", DataType::Int32, false));
914
915 let struct_array = StructArray::from(vec![
916 (b_field.clone(), boolean as ArrayRef),
917 (c_field.clone(), int as ArrayRef),
918 ]);
919
920 assert_eq!(struct_array.field(0), &b_field);
921 assert_eq!(struct_array.field(1), &c_field);
922
923 assert_eq!(struct_array.field_by_name("b"), Some(&b_field));
924 assert_eq!(struct_array.field_by_name("c"), Some(&c_field));
925 assert_eq!(struct_array.field_by_name("d"), None);
926 }
927
928 #[test]
930 fn test_struct_array_from_vec() {
931 let strings: ArrayRef = Arc::new(StringArray::from(vec![
932 Some("joe"),
933 None,
934 None,
935 Some("mark"),
936 ]));
937 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
938
939 let arr =
940 StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())]).unwrap();
941
942 let struct_data = arr.into_data();
943 assert_eq!(4, struct_data.len());
944 assert_eq!(0, struct_data.null_count());
945
946 let expected_string_data = ArrayData::builder(DataType::Utf8)
947 .len(4)
948 .null_bit_buffer(Some(Buffer::from(&[9_u8])))
949 .add_buffer(Buffer::from([0, 3, 3, 3, 7].to_byte_slice()))
950 .add_buffer(Buffer::from(b"joemark"))
951 .build()
952 .unwrap();
953
954 let expected_int_data = ArrayData::builder(DataType::Int32)
955 .len(4)
956 .null_bit_buffer(Some(Buffer::from(&[11_u8])))
957 .add_buffer(Buffer::from([1, 2, 0, 4].to_byte_slice()))
958 .build()
959 .unwrap();
960
961 assert_eq!(expected_string_data, struct_data.child_data()[0]);
962 assert_eq!(expected_int_data, struct_data.child_data()[1]);
963 }
964
965 #[test]
966 fn test_struct_array_from_vec_error() {
967 let strings: ArrayRef = Arc::new(StringArray::from(vec![
968 Some("joe"),
969 None,
970 None,
971 ]));
973 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
974
975 let err = StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())])
976 .unwrap_err()
977 .to_string();
978
979 assert_eq!(
980 err,
981 "Invalid argument error: Incorrect array length for StructArray field \"f2\", expected 3 got 4"
982 )
983 }
984
985 #[test]
986 #[should_panic(
987 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
988 )]
989 fn test_struct_array_from_mismatched_types_single() {
990 drop(StructArray::from(vec![(
991 Arc::new(Field::new("b", DataType::Int16, false)),
992 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
993 )]));
994 }
995
996 #[test]
997 #[should_panic(
998 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
999 )]
1000 fn test_struct_array_from_mismatched_types_multiple() {
1001 drop(StructArray::from(vec![
1002 (
1003 Arc::new(Field::new("b", DataType::Int16, false)),
1004 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
1005 ),
1006 (
1007 Arc::new(Field::new("c", DataType::Utf8, false)),
1008 Arc::new(Int32Array::from(vec![42, 28, 19, 31])),
1009 ),
1010 ]));
1011 }
1012
1013 #[test]
1014 fn test_struct_array_slice() {
1015 let boolean_data = ArrayData::builder(DataType::Boolean)
1016 .len(5)
1017 .add_buffer(Buffer::from([0b00010000]))
1018 .null_bit_buffer(Some(Buffer::from([0b00010001])))
1019 .build()
1020 .unwrap();
1021 let int_data = ArrayData::builder(DataType::Int32)
1022 .len(5)
1023 .add_buffer(Buffer::from([0, 28, 42, 0, 0].to_byte_slice()))
1024 .null_bit_buffer(Some(Buffer::from([0b00000110])))
1025 .build()
1026 .unwrap();
1027
1028 let field_types = vec![
1029 Field::new("a", DataType::Boolean, true),
1030 Field::new("b", DataType::Int32, true),
1031 ];
1032 let struct_array_data = ArrayData::builder(DataType::Struct(field_types.into()))
1033 .len(5)
1034 .add_child_data(boolean_data.clone())
1035 .add_child_data(int_data.clone())
1036 .null_bit_buffer(Some(Buffer::from([0b00010111])))
1037 .build()
1038 .unwrap();
1039 let struct_array = StructArray::from(struct_array_data);
1040
1041 assert_eq!(5, struct_array.len());
1042 assert_eq!(1, struct_array.null_count());
1043 assert!(struct_array.is_valid(0));
1044 assert!(struct_array.is_valid(1));
1045 assert!(struct_array.is_valid(2));
1046 assert!(struct_array.is_null(3));
1047 assert!(struct_array.is_valid(4));
1048 assert_eq!(boolean_data, struct_array.column(0).to_data());
1049 assert_eq!(int_data, struct_array.column(1).to_data());
1050
1051 let c0 = struct_array.column(0);
1052 let c0 = c0.as_any().downcast_ref::<BooleanArray>().unwrap();
1053 assert_eq!(5, c0.len());
1054 assert_eq!(3, c0.null_count());
1055 assert!(c0.is_valid(0));
1056 assert!(!c0.value(0));
1057 assert!(c0.is_null(1));
1058 assert!(c0.is_null(2));
1059 assert!(c0.is_null(3));
1060 assert!(c0.is_valid(4));
1061 assert!(c0.value(4));
1062
1063 let c1 = struct_array.column(1);
1064 let c1 = c1.as_any().downcast_ref::<Int32Array>().unwrap();
1065 assert_eq!(5, c1.len());
1066 assert_eq!(3, c1.null_count());
1067 assert!(c1.is_null(0));
1068 assert!(c1.is_valid(1));
1069 assert_eq!(28, c1.value(1));
1070 assert!(c1.is_valid(2));
1071 assert_eq!(42, c1.value(2));
1072 assert!(c1.is_null(3));
1073 assert!(c1.is_null(4));
1074
1075 let sliced_array = struct_array.slice(2, 3);
1076 let sliced_array = sliced_array.as_any().downcast_ref::<StructArray>().unwrap();
1077 assert_eq!(3, sliced_array.len());
1078 assert_eq!(1, sliced_array.null_count());
1079 assert!(sliced_array.is_valid(0));
1080 assert!(sliced_array.is_null(1));
1081 assert!(sliced_array.is_valid(2));
1082
1083 let sliced_c0 = sliced_array.column(0);
1084 let sliced_c0 = sliced_c0.as_any().downcast_ref::<BooleanArray>().unwrap();
1085 assert_eq!(3, sliced_c0.len());
1086 assert!(sliced_c0.is_null(0));
1087 assert!(sliced_c0.is_null(1));
1088 assert!(sliced_c0.is_valid(2));
1089 assert!(sliced_c0.value(2));
1090
1091 let sliced_c1 = sliced_array.column(1);
1092 let sliced_c1 = sliced_c1.as_any().downcast_ref::<Int32Array>().unwrap();
1093 assert_eq!(3, sliced_c1.len());
1094 assert!(sliced_c1.is_valid(0));
1095 assert_eq!(42, sliced_c1.value(0));
1096 assert!(sliced_c1.is_null(1));
1097 assert!(sliced_c1.is_null(2));
1098 }
1099
1100 #[test]
1101 #[should_panic(
1102 expected = "Incorrect array length for StructArray field \\\"c\\\", expected 1 got 2"
1103 )]
1104 fn test_invalid_struct_child_array_lengths() {
1105 drop(StructArray::from(vec![
1106 (
1107 Arc::new(Field::new("b", DataType::Float32, false)),
1108 Arc::new(Float32Array::from(vec![1.1])) as Arc<dyn Array>,
1109 ),
1110 (
1111 Arc::new(Field::new("c", DataType::Float64, false)),
1112 Arc::new(Float64Array::from(vec![2.2, 3.3])),
1113 ),
1114 ]));
1115 }
1116
1117 #[test]
1118 #[should_panic(expected = "use StructArray::try_new_with_length")]
1119 fn test_struct_array_from_empty() {
1120 let _ = StructArray::from(vec![]);
1123 }
1124
1125 #[test]
1126 fn test_empty_struct_array() {
1127 assert!(StructArray::try_new(Fields::empty(), vec![], None).is_err());
1128
1129 let arr = StructArray::new_empty_fields(10, None);
1130 assert_eq!(arr.len(), 10);
1131 assert_eq!(arr.null_count(), 0);
1132 assert_eq!(arr.num_columns(), 0);
1133
1134 let arr2 = StructArray::try_new_with_length(Fields::empty(), vec![], None, 10).unwrap();
1135 assert_eq!(arr2.len(), 10);
1136
1137 let arr = StructArray::new_empty_fields(10, Some(NullBuffer::new_null(10)));
1138 assert_eq!(arr.len(), 10);
1139 assert_eq!(arr.null_count(), 10);
1140 assert_eq!(arr.num_columns(), 0);
1141
1142 let arr2 = StructArray::try_new_with_length(
1143 Fields::empty(),
1144 vec![],
1145 Some(NullBuffer::new_null(10)),
1146 10,
1147 )
1148 .unwrap();
1149 assert_eq!(arr2.len(), 10);
1150 }
1151
1152 #[test]
1153 #[should_panic(expected = "Found unmasked nulls for non-nullable StructArray field \\\"c\\\"")]
1154 fn test_struct_array_from_mismatched_nullability() {
1155 drop(StructArray::from(vec![(
1156 Arc::new(Field::new("c", DataType::Int32, false)),
1157 Arc::new(Int32Array::from(vec![Some(42), None, Some(19)])) as ArrayRef,
1158 )]));
1159 }
1160
1161 #[test]
1162 fn test_struct_array_fmt_debug() {
1163 let arr = StructArray::new(
1164 vec![Arc::new(Field::new("c", DataType::Int32, true))].into(),
1165 vec![Arc::new(Int32Array::from((0..30).collect::<Vec<_>>())) as ArrayRef],
1166 Some(NullBuffer::new(BooleanBuffer::from(
1167 (0..30).map(|i| i % 2 == 0).collect::<Vec<_>>(),
1168 ))),
1169 );
1170 assert_eq!(
1171 format!("{arr:?}"),
1172 "StructArray\n-- validity:\n[\n valid,\n null,\n valid,\n null,\n valid,\n null,\n valid,\n null,\n valid,\n null,\n ...10 elements...,\n valid,\n null,\n valid,\n null,\n valid,\n null,\n valid,\n null,\n valid,\n null,\n]\n[\n-- child 0: \"c\" (Int32)\nPrimitiveArray<Int32>\n[\n 0,\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n ...10 elements...,\n 20,\n 21,\n 22,\n 23,\n 24,\n 25,\n 26,\n 27,\n 28,\n 29,\n]\n]"
1173 )
1174 }
1175
1176 #[test]
1177 fn test_struct_array_logical_nulls() {
1178 let field = Field::new("a", DataType::Int32, false);
1180 let values = vec![1, 2, 3];
1181 let nulls = NullBuffer::from(vec![true, true, true]);
1183 let array = Int32Array::new(values.into(), Some(nulls));
1184 let child = Arc::new(array) as ArrayRef;
1185 assert!(child.logical_nulls().is_some());
1186 assert_eq!(child.logical_nulls().unwrap().null_count(), 0);
1187
1188 let fields = Fields::from(vec![field]);
1189 let arrays = vec![child];
1190 let nulls = None;
1191
1192 StructArray::try_new(fields, arrays, nulls).expect("should not error");
1193 }
1194
1195 #[test]
1196 fn test_flatten_no_nulls() {
1197 let child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1198 let sa = StructArray::from(vec![(
1199 Arc::new(Field::new("a", DataType::Int32, false)),
1200 child,
1201 )]);
1202
1203 let (fields, columns) = sa.flatten();
1204
1205 assert_eq!(columns.len(), 1);
1206 assert!(!fields[0].is_nullable());
1207 assert_eq!(columns[0].null_count(), 0);
1208 assert_eq!(columns[0].len(), 3);
1209 }
1210
1211 #[test]
1212 fn test_flatten_struct_nulls_child_no_nulls() {
1213 let child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1214 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1215 let sa = StructArray::new(
1216 Fields::from(vec![Field::new("a", DataType::Int32, false)]),
1217 vec![child],
1218 Some(struct_nulls),
1219 );
1220
1221 let (fields, columns) = sa.flatten();
1222
1223 assert!(fields[0].is_nullable());
1224 assert!(columns[0].is_valid(0));
1225 assert!(columns[0].is_null(1));
1226 assert!(columns[0].is_valid(2));
1227 assert_eq!(columns[0].null_count(), 1);
1228 }
1229
1230 #[test]
1231 fn test_flatten_both_have_nulls() {
1232 let child = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)])) as ArrayRef;
1236 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true, true]));
1237 let sa = StructArray::new(
1238 Fields::from(vec![Field::new("a", DataType::Int32, true)]),
1239 vec![child],
1240 Some(struct_nulls),
1241 );
1242
1243 let (fields, columns) = sa.flatten();
1244
1245 assert!(fields[0].is_nullable());
1246 assert!(columns[0].is_valid(0));
1247 assert!(columns[0].is_null(1));
1248 assert!(columns[0].is_null(2));
1249 assert!(columns[0].is_valid(3));
1250 assert_eq!(columns[0].null_count(), 2);
1251 }
1252
1253 #[test]
1254 fn test_flatten_sliced_struct() {
1255 let child = Arc::new(Int32Array::from(vec![1, 2, 3, 4])) as ArrayRef;
1256 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true, false]));
1257 let sa = StructArray::new(
1258 Fields::from(vec![Field::new("a", DataType::Int32, false)]),
1259 vec![child],
1260 Some(struct_nulls),
1261 );
1262 let sliced = sa.slice(1, 2);
1263
1264 let (fields, columns) = sliced.flatten();
1265
1266 assert!(fields[0].is_nullable());
1267 assert_eq!(columns[0].len(), 2);
1268 assert!(columns[0].is_null(0));
1269 assert!(columns[0].is_valid(1));
1270 }
1271
1272 #[test]
1273 fn test_flatten_multiple_children() {
1274 let int_child = Arc::new(Int32Array::from(vec![Some(1), Some(2), None])) as ArrayRef;
1275 let str_child = Arc::new(StringArray::from(vec![Some("a"), None, Some("c")])) as ArrayRef;
1276 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1277 let sa = StructArray::new(
1278 Fields::from(vec![
1279 Field::new("ints", DataType::Int32, true),
1280 Field::new("strs", DataType::Utf8, true),
1281 ]),
1282 vec![int_child, str_child],
1283 Some(struct_nulls),
1284 );
1285
1286 let (fields, columns) = sa.flatten();
1287
1288 assert_eq!(fields.len(), 2);
1289 assert_eq!(columns[0].null_count(), 2);
1291 assert!(columns[0].is_valid(0));
1292 assert!(columns[0].is_null(1));
1293 assert!(columns[0].is_null(2));
1294 assert_eq!(columns[1].null_count(), 1);
1296 assert!(columns[1].is_valid(0));
1297 assert!(columns[1].is_null(1));
1298 assert!(columns[1].is_valid(2));
1299 }
1300
1301 #[test]
1302 fn test_flatten_empty_struct() {
1303 let sa = StructArray::new_empty_fields(5, Some(NullBuffer::new_null(5)));
1304
1305 let (fields, columns) = sa.flatten();
1306
1307 assert_eq!(fields.len(), 0);
1308 assert_eq!(columns.len(), 0);
1309 }
1310
1311 #[test]
1312 fn test_flatten_field_nullability_update() {
1313 let non_null_child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1314 let nullable_child = Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])) as ArrayRef;
1315 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
1316 let sa = StructArray::new(
1317 Fields::from(vec![
1318 Field::new("non_null", DataType::Int32, false),
1319 Field::new("nullable", DataType::Int32, true),
1320 ]),
1321 vec![non_null_child, nullable_child],
1322 Some(struct_nulls),
1323 );
1324
1325 let (fields, _columns) = sa.flatten();
1326
1327 assert!(fields[0].is_nullable()); assert!(fields[1].is_nullable()); }
1330}