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 if n.len() != len {
143 return Err(ArrowError::InvalidArgumentError(format!(
144 "Incorrect number of nulls for StructArray, expected {len} got {}",
145 n.len(),
146 )));
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 if let Some(a) = a.logical_nulls() {
171 if !nulls.as_ref().map(|n| n.contains(&a)).unwrap_or_default()
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 }
182
183 Ok(Self {
184 len,
185 data_type: DataType::Struct(fields),
186 nulls: nulls.filter(|n| n.null_count() > 0),
187 fields: arrays,
188 })
189 }
190
191 pub fn new_null(fields: Fields, len: usize) -> Self {
193 let arrays = fields
194 .iter()
195 .map(|f| new_null_array(f.data_type(), len))
196 .collect();
197
198 Self {
199 len,
200 data_type: DataType::Struct(fields),
201 nulls: Some(NullBuffer::new_null(len)),
202 fields: arrays,
203 }
204 }
205
206 pub unsafe fn new_unchecked(
216 fields: Fields,
217 arrays: Vec<ArrayRef>,
218 nulls: Option<NullBuffer>,
219 ) -> Self {
220 if cfg!(feature = "force_validate") {
221 return Self::new(fields, arrays, nulls);
222 }
223
224 let len = arrays.first().map(|x| x.len()).expect(
225 "cannot use StructArray::new_unchecked if there are no fields, length is unknown",
226 );
227 Self {
228 len,
229 data_type: DataType::Struct(fields),
230 nulls,
231 fields: arrays,
232 }
233 }
234
235 pub unsafe fn new_unchecked_with_length(
241 fields: Fields,
242 arrays: Vec<ArrayRef>,
243 nulls: Option<NullBuffer>,
244 len: usize,
245 ) -> Self {
246 if cfg!(feature = "force_validate") {
247 return Self::try_new_with_length(fields, arrays, nulls, len).unwrap();
248 }
249
250 Self {
251 len,
252 data_type: DataType::Struct(fields),
253 nulls,
254 fields: arrays,
255 }
256 }
257
258 pub fn new_empty_fields(len: usize, nulls: Option<NullBuffer>) -> Self {
264 if let Some(n) = &nulls {
265 assert_eq!(len, n.len())
266 }
267 Self {
268 len,
269 data_type: DataType::Struct(Fields::empty()),
270 fields: vec![],
271 nulls,
272 }
273 }
274
275 pub fn into_parts(self) -> (Fields, Vec<ArrayRef>, Option<NullBuffer>) {
277 let f = match self.data_type {
278 DataType::Struct(f) => f,
279 _ => unreachable!(),
280 };
281 (f, self.fields, self.nulls)
282 }
283
284 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.column_names()
325 .iter()
326 .position(|c| c == &column_name)
327 .map(|pos| self.column(pos))
328 }
329
330 pub fn slice(&self, offset: usize, len: usize) -> Self {
332 assert!(
333 offset.saturating_add(len) <= self.len,
334 "the length + offset of the sliced StructArray cannot exceed the existing length"
335 );
336
337 let fields = self.fields.iter().map(|a| a.slice(offset, len)).collect();
338
339 Self {
340 len,
341 data_type: self.data_type.clone(),
342 nulls: self.nulls.as_ref().map(|n| n.slice(offset, len)),
343 fields,
344 }
345 }
346
347 pub fn flatten(&self) -> (Fields, Vec<ArrayRef>) {
377 let schema_fields = self.fields();
378
379 let struct_nulls = match &self.nulls {
380 Some(n) => n,
381 None => return (schema_fields.clone(), self.fields.clone()),
382 };
383
384 let new_fields: Fields = schema_fields
385 .iter()
386 .map(|f| {
387 if f.is_nullable() {
388 Arc::clone(f)
389 } else {
390 Arc::new(f.as_ref().clone().with_nullable(true))
391 }
392 })
393 .collect::<Vec<_>>()
394 .into();
395
396 let new_columns = self
397 .fields
398 .iter()
399 .map(|child| {
400 let merged = NullBuffer::union(Some(struct_nulls), child.nulls());
401 let data = child.to_data().into_builder().nulls(merged);
404 make_array(unsafe { data.build_unchecked() })
405 })
406 .collect();
407
408 (new_fields, new_columns)
409 }
410}
411
412impl From<ArrayData> for StructArray {
413 fn from(data: ArrayData) -> Self {
414 let (data_type, len, nulls, offset, _buffers, child_data) = data.into_parts();
415
416 let parent_offset = offset;
417 let parent_len = len;
418
419 let fields = child_data
420 .into_iter()
421 .map(|cd| {
422 if parent_offset != 0 || parent_len != cd.len() {
423 make_array(cd.slice(parent_offset, parent_len))
424 } else {
425 make_array(cd)
426 }
427 })
428 .collect();
429
430 Self {
431 len,
432 data_type,
433 nulls,
434 fields,
435 }
436 }
437}
438
439impl From<StructArray> for ArrayData {
440 fn from(array: StructArray) -> Self {
441 let builder = ArrayDataBuilder::new(array.data_type)
442 .len(array.len)
443 .nulls(array.nulls)
444 .child_data(array.fields.iter().map(|x| x.to_data()).collect());
445
446 unsafe { builder.build_unchecked() }
447 }
448}
449
450impl TryFrom<Vec<(&str, ArrayRef)>> for StructArray {
451 type Error = ArrowError;
452
453 fn try_from(values: Vec<(&str, ArrayRef)>) -> Result<Self, ArrowError> {
455 let (fields, arrays): (Vec<_>, _) = values
456 .into_iter()
457 .map(|(name, array)| {
458 (
459 Field::new(name, array.data_type().clone(), array.is_nullable()),
460 array,
461 )
462 })
463 .unzip();
464
465 StructArray::try_new(fields.into(), arrays, None)
466 }
467}
468
469unsafe impl Array for StructArray {
471 fn as_any(&self) -> &dyn Any {
472 self
473 }
474
475 fn to_data(&self) -> ArrayData {
476 self.clone().into()
477 }
478
479 fn into_data(self) -> ArrayData {
480 self.into()
481 }
482
483 fn data_type(&self) -> &DataType {
484 &self.data_type
485 }
486
487 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
488 Arc::new(self.slice(offset, length))
489 }
490
491 fn len(&self) -> usize {
492 self.len
493 }
494
495 fn is_empty(&self) -> bool {
496 self.len == 0
497 }
498
499 fn shrink_to_fit(&mut self) {
500 if let Some(nulls) = &mut self.nulls {
501 nulls.shrink_to_fit();
502 }
503 self.fields.iter_mut().for_each(|n| n.shrink_to_fit());
504 }
505
506 fn offset(&self) -> usize {
507 0
508 }
509
510 fn nulls(&self) -> Option<&NullBuffer> {
511 self.nulls.as_ref()
512 }
513
514 fn logical_null_count(&self) -> usize {
515 self.null_count()
517 }
518
519 fn get_buffer_memory_size(&self) -> usize {
520 let mut size = self.fields.iter().map(|a| a.get_buffer_memory_size()).sum();
521 if let Some(n) = self.nulls.as_ref() {
522 size += n.buffer().capacity();
523 }
524 size
525 }
526
527 fn get_array_memory_size(&self) -> usize {
528 let mut size = self.fields.iter().map(|a| a.get_array_memory_size()).sum();
529 size += std::mem::size_of::<Self>();
530 if let Some(n) = self.nulls.as_ref() {
531 size += n.buffer().capacity();
532 }
533 size
534 }
535
536 #[cfg(feature = "pool")]
537 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
538 for field in &self.fields {
539 field.claim(pool);
540 }
541 if let Some(nulls) = &self.nulls {
542 nulls.claim(pool);
543 }
544 }
545}
546
547impl From<Vec<(FieldRef, ArrayRef)>> for StructArray {
548 fn from(v: Vec<(FieldRef, ArrayRef)>) -> Self {
549 let (fields, arrays): (Vec<_>, _) = v.into_iter().unzip();
550 StructArray::new(fields.into(), arrays, None)
551 }
552}
553
554impl std::fmt::Debug for StructArray {
555 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
556 writeln!(f, "StructArray")?;
557 writeln!(f, "-- validity:")?;
558 writeln!(f, "[")?;
559 print_long_array(self, f, |_array, _index, f| write!(f, "valid"))?;
560 writeln!(f, "]\n[")?;
561 for (child_index, name) in self.column_names().iter().enumerate() {
562 let column = self.column(child_index);
563 writeln!(
564 f,
565 "-- child {}: \"{}\" ({:?})",
566 child_index,
567 name,
568 column.data_type()
569 )?;
570 std::fmt::Debug::fmt(column, f)?;
571 writeln!(f)?;
572 }
573 write!(f, "]")
574 }
575}
576
577impl From<(Vec<(FieldRef, ArrayRef)>, Buffer)> for StructArray {
578 fn from(pair: (Vec<(FieldRef, ArrayRef)>, Buffer)) -> Self {
579 let len = pair.0.first().map(|x| x.1.len()).unwrap_or_default();
580 let (fields, arrays): (Vec<_>, Vec<_>) = pair.0.into_iter().unzip();
581 let nulls = NullBuffer::new(BooleanBuffer::new(pair.1, 0, len));
582 Self::new(fields.into(), arrays, Some(nulls))
583 }
584}
585
586impl From<RecordBatch> for StructArray {
587 fn from(value: RecordBatch) -> Self {
588 Self {
589 len: value.num_rows(),
590 data_type: DataType::Struct(value.schema().fields().clone()),
591 nulls: None,
592 fields: value.columns().to_vec(),
593 }
594 }
595}
596
597impl Index<&str> for StructArray {
598 type Output = ArrayRef;
599
600 fn index(&self, name: &str) -> &Self::Output {
610 self.column_by_name(name).unwrap()
611 }
612}
613
614#[cfg(test)]
615mod tests {
616 use super::*;
617
618 use crate::{BooleanArray, Float32Array, Float64Array, Int32Array, Int64Array, StringArray};
619 use arrow_buffer::ToByteSlice;
620
621 #[test]
622 fn test_struct_array_builder() {
623 let boolean_array = BooleanArray::from(vec![false, false, true, true]);
624 let int_array = Int64Array::from(vec![42, 28, 19, 31]);
625
626 let fields = vec![
627 Field::new("a", DataType::Boolean, false),
628 Field::new("b", DataType::Int64, false),
629 ];
630 let struct_array_data = ArrayData::builder(DataType::Struct(fields.into()))
631 .len(4)
632 .add_child_data(boolean_array.to_data())
633 .add_child_data(int_array.to_data())
634 .build()
635 .unwrap();
636 let struct_array = StructArray::from(struct_array_data);
637
638 assert_eq!(struct_array.column(0).as_ref(), &boolean_array);
639 assert_eq!(struct_array.column(1).as_ref(), &int_array);
640 }
641
642 #[test]
643 fn test_struct_array_from() {
644 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
645 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
646
647 let struct_array = StructArray::from(vec![
648 (
649 Arc::new(Field::new("b", DataType::Boolean, false)),
650 boolean.clone() as ArrayRef,
651 ),
652 (
653 Arc::new(Field::new("c", DataType::Int32, false)),
654 int.clone() as ArrayRef,
655 ),
656 ]);
657 assert_eq!(struct_array.column(0).as_ref(), boolean.as_ref());
658 assert_eq!(struct_array.column(1).as_ref(), int.as_ref());
659 assert_eq!(4, struct_array.len());
660 assert_eq!(0, struct_array.null_count());
661 assert_eq!(0, struct_array.offset());
662 }
663
664 #[test]
665 fn test_struct_array_from_data_with_offset_and_length() {
666 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
672 let int_field = Field::new("x", DataType::Int32, false);
673 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
674 let int_data = int_arr.to_data();
675 let case1 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
677 .len(3)
678 .offset(1)
679 .nulls(Some(struct_nulls))
680 .add_child_data(int_data.clone())
681 .build()
682 .unwrap();
683
684 let struct_nulls =
686 NullBuffer::new(BooleanBuffer::from(vec![true, true, true, false, true]).slice(1, 3));
687 let case2 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
688 .len(3)
689 .offset(1)
690 .nulls(Some(struct_nulls.clone()))
691 .add_child_data(int_data.clone())
692 .build()
693 .unwrap();
694
695 let offset_int_data = int_data.slice(1, 4);
697 let case3 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
698 .len(3)
699 .nulls(Some(struct_nulls))
700 .add_child_data(offset_int_data)
701 .build()
702 .unwrap();
703
704 let expected = StructArray::new(
705 Fields::from(vec![int_field.clone()]),
706 vec![Arc::new(int_arr)],
707 Some(NullBuffer::new(BooleanBuffer::from(vec![
708 true, true, true, false, true,
709 ]))),
710 )
711 .slice(1, 3);
712
713 for case in [case1, case2, case3] {
714 let struct_arr_from_data = StructArray::from(case);
715 assert_eq!(struct_arr_from_data, expected);
716 assert_eq!(struct_arr_from_data.column(0), expected.column(0));
717 }
718 }
719
720 #[test]
721 #[should_panic(expected = "assertion failed: (offset + length) <= self.len()")]
722 fn test_struct_array_from_data_with_offset_and_length_error() {
723 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
724 let int_field = Field::new("x", DataType::Int32, false);
725 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
726 let int_data = int_arr.to_data();
727 let struct_data =
729 ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
730 .len(3)
731 .offset(3)
732 .nulls(Some(struct_nulls))
733 .add_child_data(int_data)
734 .build()
735 .unwrap();
736 let _ = StructArray::from(struct_data);
737 }
738
739 #[test]
741 fn test_struct_array_index_access() {
742 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
743 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
744
745 let struct_array = StructArray::from(vec![
746 (
747 Arc::new(Field::new("b", DataType::Boolean, false)),
748 boolean.clone() as ArrayRef,
749 ),
750 (
751 Arc::new(Field::new("c", DataType::Int32, false)),
752 int.clone() as ArrayRef,
753 ),
754 ]);
755 assert_eq!(struct_array["b"].as_ref(), boolean.as_ref());
756 assert_eq!(struct_array["c"].as_ref(), int.as_ref());
757 }
758
759 #[test]
761 fn test_struct_array_from_vec() {
762 let strings: ArrayRef = Arc::new(StringArray::from(vec![
763 Some("joe"),
764 None,
765 None,
766 Some("mark"),
767 ]));
768 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
769
770 let arr =
771 StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())]).unwrap();
772
773 let struct_data = arr.into_data();
774 assert_eq!(4, struct_data.len());
775 assert_eq!(0, struct_data.null_count());
776
777 let expected_string_data = ArrayData::builder(DataType::Utf8)
778 .len(4)
779 .null_bit_buffer(Some(Buffer::from(&[9_u8])))
780 .add_buffer(Buffer::from([0, 3, 3, 3, 7].to_byte_slice()))
781 .add_buffer(Buffer::from(b"joemark"))
782 .build()
783 .unwrap();
784
785 let expected_int_data = ArrayData::builder(DataType::Int32)
786 .len(4)
787 .null_bit_buffer(Some(Buffer::from(&[11_u8])))
788 .add_buffer(Buffer::from([1, 2, 0, 4].to_byte_slice()))
789 .build()
790 .unwrap();
791
792 assert_eq!(expected_string_data, struct_data.child_data()[0]);
793 assert_eq!(expected_int_data, struct_data.child_data()[1]);
794 }
795
796 #[test]
797 fn test_struct_array_from_vec_error() {
798 let strings: ArrayRef = Arc::new(StringArray::from(vec![
799 Some("joe"),
800 None,
801 None,
802 ]));
804 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
805
806 let err = StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())])
807 .unwrap_err()
808 .to_string();
809
810 assert_eq!(
811 err,
812 "Invalid argument error: Incorrect array length for StructArray field \"f2\", expected 3 got 4"
813 )
814 }
815
816 #[test]
817 #[should_panic(
818 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
819 )]
820 fn test_struct_array_from_mismatched_types_single() {
821 drop(StructArray::from(vec![(
822 Arc::new(Field::new("b", DataType::Int16, false)),
823 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
824 )]));
825 }
826
827 #[test]
828 #[should_panic(
829 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
830 )]
831 fn test_struct_array_from_mismatched_types_multiple() {
832 drop(StructArray::from(vec![
833 (
834 Arc::new(Field::new("b", DataType::Int16, false)),
835 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
836 ),
837 (
838 Arc::new(Field::new("c", DataType::Utf8, false)),
839 Arc::new(Int32Array::from(vec![42, 28, 19, 31])),
840 ),
841 ]));
842 }
843
844 #[test]
845 fn test_struct_array_slice() {
846 let boolean_data = ArrayData::builder(DataType::Boolean)
847 .len(5)
848 .add_buffer(Buffer::from([0b00010000]))
849 .null_bit_buffer(Some(Buffer::from([0b00010001])))
850 .build()
851 .unwrap();
852 let int_data = ArrayData::builder(DataType::Int32)
853 .len(5)
854 .add_buffer(Buffer::from([0, 28, 42, 0, 0].to_byte_slice()))
855 .null_bit_buffer(Some(Buffer::from([0b00000110])))
856 .build()
857 .unwrap();
858
859 let field_types = vec![
860 Field::new("a", DataType::Boolean, true),
861 Field::new("b", DataType::Int32, true),
862 ];
863 let struct_array_data = ArrayData::builder(DataType::Struct(field_types.into()))
864 .len(5)
865 .add_child_data(boolean_data.clone())
866 .add_child_data(int_data.clone())
867 .null_bit_buffer(Some(Buffer::from([0b00010111])))
868 .build()
869 .unwrap();
870 let struct_array = StructArray::from(struct_array_data);
871
872 assert_eq!(5, struct_array.len());
873 assert_eq!(1, struct_array.null_count());
874 assert!(struct_array.is_valid(0));
875 assert!(struct_array.is_valid(1));
876 assert!(struct_array.is_valid(2));
877 assert!(struct_array.is_null(3));
878 assert!(struct_array.is_valid(4));
879 assert_eq!(boolean_data, struct_array.column(0).to_data());
880 assert_eq!(int_data, struct_array.column(1).to_data());
881
882 let c0 = struct_array.column(0);
883 let c0 = c0.as_any().downcast_ref::<BooleanArray>().unwrap();
884 assert_eq!(5, c0.len());
885 assert_eq!(3, c0.null_count());
886 assert!(c0.is_valid(0));
887 assert!(!c0.value(0));
888 assert!(c0.is_null(1));
889 assert!(c0.is_null(2));
890 assert!(c0.is_null(3));
891 assert!(c0.is_valid(4));
892 assert!(c0.value(4));
893
894 let c1 = struct_array.column(1);
895 let c1 = c1.as_any().downcast_ref::<Int32Array>().unwrap();
896 assert_eq!(5, c1.len());
897 assert_eq!(3, c1.null_count());
898 assert!(c1.is_null(0));
899 assert!(c1.is_valid(1));
900 assert_eq!(28, c1.value(1));
901 assert!(c1.is_valid(2));
902 assert_eq!(42, c1.value(2));
903 assert!(c1.is_null(3));
904 assert!(c1.is_null(4));
905
906 let sliced_array = struct_array.slice(2, 3);
907 let sliced_array = sliced_array.as_any().downcast_ref::<StructArray>().unwrap();
908 assert_eq!(3, sliced_array.len());
909 assert_eq!(1, sliced_array.null_count());
910 assert!(sliced_array.is_valid(0));
911 assert!(sliced_array.is_null(1));
912 assert!(sliced_array.is_valid(2));
913
914 let sliced_c0 = sliced_array.column(0);
915 let sliced_c0 = sliced_c0.as_any().downcast_ref::<BooleanArray>().unwrap();
916 assert_eq!(3, sliced_c0.len());
917 assert!(sliced_c0.is_null(0));
918 assert!(sliced_c0.is_null(1));
919 assert!(sliced_c0.is_valid(2));
920 assert!(sliced_c0.value(2));
921
922 let sliced_c1 = sliced_array.column(1);
923 let sliced_c1 = sliced_c1.as_any().downcast_ref::<Int32Array>().unwrap();
924 assert_eq!(3, sliced_c1.len());
925 assert!(sliced_c1.is_valid(0));
926 assert_eq!(42, sliced_c1.value(0));
927 assert!(sliced_c1.is_null(1));
928 assert!(sliced_c1.is_null(2));
929 }
930
931 #[test]
932 #[should_panic(
933 expected = "Incorrect array length for StructArray field \\\"c\\\", expected 1 got 2"
934 )]
935 fn test_invalid_struct_child_array_lengths() {
936 drop(StructArray::from(vec![
937 (
938 Arc::new(Field::new("b", DataType::Float32, false)),
939 Arc::new(Float32Array::from(vec![1.1])) as Arc<dyn Array>,
940 ),
941 (
942 Arc::new(Field::new("c", DataType::Float64, false)),
943 Arc::new(Float64Array::from(vec![2.2, 3.3])),
944 ),
945 ]));
946 }
947
948 #[test]
949 #[should_panic(expected = "use StructArray::try_new_with_length")]
950 fn test_struct_array_from_empty() {
951 let _ = StructArray::from(vec![]);
954 }
955
956 #[test]
957 fn test_empty_struct_array() {
958 assert!(StructArray::try_new(Fields::empty(), vec![], None).is_err());
959
960 let arr = StructArray::new_empty_fields(10, None);
961 assert_eq!(arr.len(), 10);
962 assert_eq!(arr.null_count(), 0);
963 assert_eq!(arr.num_columns(), 0);
964
965 let arr2 = StructArray::try_new_with_length(Fields::empty(), vec![], None, 10).unwrap();
966 assert_eq!(arr2.len(), 10);
967
968 let arr = StructArray::new_empty_fields(10, Some(NullBuffer::new_null(10)));
969 assert_eq!(arr.len(), 10);
970 assert_eq!(arr.null_count(), 10);
971 assert_eq!(arr.num_columns(), 0);
972
973 let arr2 = StructArray::try_new_with_length(
974 Fields::empty(),
975 vec![],
976 Some(NullBuffer::new_null(10)),
977 10,
978 )
979 .unwrap();
980 assert_eq!(arr2.len(), 10);
981 }
982
983 #[test]
984 #[should_panic(expected = "Found unmasked nulls for non-nullable StructArray field \\\"c\\\"")]
985 fn test_struct_array_from_mismatched_nullability() {
986 drop(StructArray::from(vec![(
987 Arc::new(Field::new("c", DataType::Int32, false)),
988 Arc::new(Int32Array::from(vec![Some(42), None, Some(19)])) as ArrayRef,
989 )]));
990 }
991
992 #[test]
993 fn test_struct_array_fmt_debug() {
994 let arr: StructArray = StructArray::new(
995 vec![Arc::new(Field::new("c", DataType::Int32, true))].into(),
996 vec![Arc::new(Int32Array::from((0..30).collect::<Vec<_>>())) as ArrayRef],
997 Some(NullBuffer::new(BooleanBuffer::from(
998 (0..30).map(|i| i % 2 == 0).collect::<Vec<_>>(),
999 ))),
1000 );
1001 assert_eq!(
1002 format!("{arr:?}"),
1003 "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]"
1004 )
1005 }
1006
1007 #[test]
1008 fn test_struct_array_logical_nulls() {
1009 let field = Field::new("a", DataType::Int32, false);
1011 let values = vec![1, 2, 3];
1012 let nulls = NullBuffer::from(vec![true, true, true]);
1014 let array = Int32Array::new(values.into(), Some(nulls));
1015 let child = Arc::new(array) as ArrayRef;
1016 assert!(child.logical_nulls().is_some());
1017 assert_eq!(child.logical_nulls().unwrap().null_count(), 0);
1018
1019 let fields = Fields::from(vec![field]);
1020 let arrays = vec![child];
1021 let nulls = None;
1022
1023 StructArray::try_new(fields, arrays, nulls).expect("should not error");
1024 }
1025
1026 #[test]
1027 fn test_flatten_no_nulls() {
1028 let child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1029 let sa = StructArray::from(vec![(
1030 Arc::new(Field::new("a", DataType::Int32, false)),
1031 child,
1032 )]);
1033
1034 let (fields, columns) = sa.flatten();
1035
1036 assert_eq!(columns.len(), 1);
1037 assert!(!fields[0].is_nullable());
1038 assert_eq!(columns[0].null_count(), 0);
1039 assert_eq!(columns[0].len(), 3);
1040 }
1041
1042 #[test]
1043 fn test_flatten_struct_nulls_child_no_nulls() {
1044 let child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1045 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1046 let sa = StructArray::new(
1047 Fields::from(vec![Field::new("a", DataType::Int32, false)]),
1048 vec![child],
1049 Some(struct_nulls),
1050 );
1051
1052 let (fields, columns) = sa.flatten();
1053
1054 assert!(fields[0].is_nullable());
1055 assert!(columns[0].is_valid(0));
1056 assert!(columns[0].is_null(1));
1057 assert!(columns[0].is_valid(2));
1058 assert_eq!(columns[0].null_count(), 1);
1059 }
1060
1061 #[test]
1062 fn test_flatten_both_have_nulls() {
1063 let child = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)])) as ArrayRef;
1067 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true, true]));
1068 let sa = StructArray::new(
1069 Fields::from(vec![Field::new("a", DataType::Int32, true)]),
1070 vec![child],
1071 Some(struct_nulls),
1072 );
1073
1074 let (fields, columns) = sa.flatten();
1075
1076 assert!(fields[0].is_nullable());
1077 assert!(columns[0].is_valid(0));
1078 assert!(columns[0].is_null(1));
1079 assert!(columns[0].is_null(2));
1080 assert!(columns[0].is_valid(3));
1081 assert_eq!(columns[0].null_count(), 2);
1082 }
1083
1084 #[test]
1085 fn test_flatten_sliced_struct() {
1086 let child = Arc::new(Int32Array::from(vec![1, 2, 3, 4])) as ArrayRef;
1087 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true, false]));
1088 let sa = StructArray::new(
1089 Fields::from(vec![Field::new("a", DataType::Int32, false)]),
1090 vec![child],
1091 Some(struct_nulls),
1092 );
1093 let sliced = sa.slice(1, 2);
1094
1095 let (fields, columns) = sliced.flatten();
1096
1097 assert!(fields[0].is_nullable());
1098 assert_eq!(columns[0].len(), 2);
1099 assert!(columns[0].is_null(0));
1100 assert!(columns[0].is_valid(1));
1101 }
1102
1103 #[test]
1104 fn test_flatten_multiple_children() {
1105 let int_child = Arc::new(Int32Array::from(vec![Some(1), Some(2), None])) as ArrayRef;
1106 let str_child = Arc::new(StringArray::from(vec![Some("a"), None, Some("c")])) as ArrayRef;
1107 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1108 let sa = StructArray::new(
1109 Fields::from(vec![
1110 Field::new("ints", DataType::Int32, true),
1111 Field::new("strs", DataType::Utf8, true),
1112 ]),
1113 vec![int_child, str_child],
1114 Some(struct_nulls),
1115 );
1116
1117 let (fields, columns) = sa.flatten();
1118
1119 assert_eq!(fields.len(), 2);
1120 assert_eq!(columns[0].null_count(), 2);
1122 assert!(columns[0].is_valid(0));
1123 assert!(columns[0].is_null(1));
1124 assert!(columns[0].is_null(2));
1125 assert_eq!(columns[1].null_count(), 1);
1127 assert!(columns[1].is_valid(0));
1128 assert!(columns[1].is_null(1));
1129 assert!(columns[1].is_valid(2));
1130 }
1131
1132 #[test]
1133 fn test_flatten_empty_struct() {
1134 let sa = StructArray::new_empty_fields(5, Some(NullBuffer::new_null(5)));
1135
1136 let (fields, columns) = sa.flatten();
1137
1138 assert_eq!(fields.len(), 0);
1139 assert_eq!(columns.len(), 0);
1140 }
1141
1142 #[test]
1143 fn test_flatten_field_nullability_update() {
1144 let non_null_child = Arc::new(Int32Array::from(vec![1, 2, 3])) as ArrayRef;
1145 let nullable_child = Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])) as ArrayRef;
1146 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
1147 let sa = StructArray::new(
1148 Fields::from(vec![
1149 Field::new("non_null", DataType::Int32, false),
1150 Field::new("nullable", DataType::Int32, true),
1151 ]),
1152 vec![non_null_child, nullable_child],
1153 Some(struct_nulls),
1154 );
1155
1156 let (fields, _columns) = sa.flatten();
1157
1158 assert!(fields[0].is_nullable()); assert!(fields[1].is_nullable()); }
1161}