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
348impl From<ArrayData> for StructArray {
349 fn from(data: ArrayData) -> Self {
350 let (data_type, len, nulls, offset, _buffers, child_data) = data.into_parts();
351
352 let parent_offset = offset;
353 let parent_len = len;
354
355 let fields = child_data
356 .into_iter()
357 .map(|cd| {
358 if parent_offset != 0 || parent_len != cd.len() {
359 make_array(cd.slice(parent_offset, parent_len))
360 } else {
361 make_array(cd)
362 }
363 })
364 .collect();
365
366 Self {
367 len,
368 data_type,
369 nulls,
370 fields,
371 }
372 }
373}
374
375impl From<StructArray> for ArrayData {
376 fn from(array: StructArray) -> Self {
377 let builder = ArrayDataBuilder::new(array.data_type)
378 .len(array.len)
379 .nulls(array.nulls)
380 .child_data(array.fields.iter().map(|x| x.to_data()).collect());
381
382 unsafe { builder.build_unchecked() }
383 }
384}
385
386impl TryFrom<Vec<(&str, ArrayRef)>> for StructArray {
387 type Error = ArrowError;
388
389 fn try_from(values: Vec<(&str, ArrayRef)>) -> Result<Self, ArrowError> {
391 let (fields, arrays): (Vec<_>, _) = values
392 .into_iter()
393 .map(|(name, array)| {
394 (
395 Field::new(name, array.data_type().clone(), array.is_nullable()),
396 array,
397 )
398 })
399 .unzip();
400
401 StructArray::try_new(fields.into(), arrays, None)
402 }
403}
404
405unsafe impl Array for StructArray {
407 fn as_any(&self) -> &dyn Any {
408 self
409 }
410
411 fn to_data(&self) -> ArrayData {
412 self.clone().into()
413 }
414
415 fn into_data(self) -> ArrayData {
416 self.into()
417 }
418
419 fn data_type(&self) -> &DataType {
420 &self.data_type
421 }
422
423 fn slice(&self, offset: usize, length: usize) -> ArrayRef {
424 Arc::new(self.slice(offset, length))
425 }
426
427 fn len(&self) -> usize {
428 self.len
429 }
430
431 fn is_empty(&self) -> bool {
432 self.len == 0
433 }
434
435 fn shrink_to_fit(&mut self) {
436 if let Some(nulls) = &mut self.nulls {
437 nulls.shrink_to_fit();
438 }
439 self.fields.iter_mut().for_each(|n| n.shrink_to_fit());
440 }
441
442 fn offset(&self) -> usize {
443 0
444 }
445
446 fn nulls(&self) -> Option<&NullBuffer> {
447 self.nulls.as_ref()
448 }
449
450 fn logical_null_count(&self) -> usize {
451 self.null_count()
453 }
454
455 fn get_buffer_memory_size(&self) -> usize {
456 let mut size = self.fields.iter().map(|a| a.get_buffer_memory_size()).sum();
457 if let Some(n) = self.nulls.as_ref() {
458 size += n.buffer().capacity();
459 }
460 size
461 }
462
463 fn get_array_memory_size(&self) -> usize {
464 let mut size = self.fields.iter().map(|a| a.get_array_memory_size()).sum();
465 size += std::mem::size_of::<Self>();
466 if let Some(n) = self.nulls.as_ref() {
467 size += n.buffer().capacity();
468 }
469 size
470 }
471
472 #[cfg(feature = "pool")]
473 fn claim(&self, pool: &dyn arrow_buffer::MemoryPool) {
474 for field in &self.fields {
475 field.claim(pool);
476 }
477 if let Some(nulls) = &self.nulls {
478 nulls.claim(pool);
479 }
480 }
481}
482
483impl From<Vec<(FieldRef, ArrayRef)>> for StructArray {
484 fn from(v: Vec<(FieldRef, ArrayRef)>) -> Self {
485 let (fields, arrays): (Vec<_>, _) = v.into_iter().unzip();
486 StructArray::new(fields.into(), arrays, None)
487 }
488}
489
490impl std::fmt::Debug for StructArray {
491 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
492 writeln!(f, "StructArray")?;
493 writeln!(f, "-- validity:")?;
494 writeln!(f, "[")?;
495 print_long_array(self, f, |_array, _index, f| write!(f, "valid"))?;
496 writeln!(f, "]\n[")?;
497 for (child_index, name) in self.column_names().iter().enumerate() {
498 let column = self.column(child_index);
499 writeln!(
500 f,
501 "-- child {}: \"{}\" ({:?})",
502 child_index,
503 name,
504 column.data_type()
505 )?;
506 std::fmt::Debug::fmt(column, f)?;
507 writeln!(f)?;
508 }
509 write!(f, "]")
510 }
511}
512
513impl From<(Vec<(FieldRef, ArrayRef)>, Buffer)> for StructArray {
514 fn from(pair: (Vec<(FieldRef, ArrayRef)>, Buffer)) -> Self {
515 let len = pair.0.first().map(|x| x.1.len()).unwrap_or_default();
516 let (fields, arrays): (Vec<_>, Vec<_>) = pair.0.into_iter().unzip();
517 let nulls = NullBuffer::new(BooleanBuffer::new(pair.1, 0, len));
518 Self::new(fields.into(), arrays, Some(nulls))
519 }
520}
521
522impl From<RecordBatch> for StructArray {
523 fn from(value: RecordBatch) -> Self {
524 Self {
525 len: value.num_rows(),
526 data_type: DataType::Struct(value.schema().fields().clone()),
527 nulls: None,
528 fields: value.columns().to_vec(),
529 }
530 }
531}
532
533impl Index<&str> for StructArray {
534 type Output = ArrayRef;
535
536 fn index(&self, name: &str) -> &Self::Output {
546 self.column_by_name(name).unwrap()
547 }
548}
549
550#[cfg(test)]
551mod tests {
552 use super::*;
553
554 use crate::{BooleanArray, Float32Array, Float64Array, Int32Array, Int64Array, StringArray};
555 use arrow_buffer::ToByteSlice;
556
557 #[test]
558 fn test_struct_array_builder() {
559 let boolean_array = BooleanArray::from(vec![false, false, true, true]);
560 let int_array = Int64Array::from(vec![42, 28, 19, 31]);
561
562 let fields = vec![
563 Field::new("a", DataType::Boolean, false),
564 Field::new("b", DataType::Int64, false),
565 ];
566 let struct_array_data = ArrayData::builder(DataType::Struct(fields.into()))
567 .len(4)
568 .add_child_data(boolean_array.to_data())
569 .add_child_data(int_array.to_data())
570 .build()
571 .unwrap();
572 let struct_array = StructArray::from(struct_array_data);
573
574 assert_eq!(struct_array.column(0).as_ref(), &boolean_array);
575 assert_eq!(struct_array.column(1).as_ref(), &int_array);
576 }
577
578 #[test]
579 fn test_struct_array_from() {
580 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
581 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
582
583 let struct_array = StructArray::from(vec![
584 (
585 Arc::new(Field::new("b", DataType::Boolean, false)),
586 boolean.clone() as ArrayRef,
587 ),
588 (
589 Arc::new(Field::new("c", DataType::Int32, false)),
590 int.clone() as ArrayRef,
591 ),
592 ]);
593 assert_eq!(struct_array.column(0).as_ref(), boolean.as_ref());
594 assert_eq!(struct_array.column(1).as_ref(), int.as_ref());
595 assert_eq!(4, struct_array.len());
596 assert_eq!(0, struct_array.null_count());
597 assert_eq!(0, struct_array.offset());
598 }
599
600 #[test]
601 fn test_struct_array_from_data_with_offset_and_length() {
602 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
608 let int_field = Field::new("x", DataType::Int32, false);
609 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
610 let int_data = int_arr.to_data();
611 let case1 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
613 .len(3)
614 .offset(1)
615 .nulls(Some(struct_nulls))
616 .add_child_data(int_data.clone())
617 .build()
618 .unwrap();
619
620 let struct_nulls =
622 NullBuffer::new(BooleanBuffer::from(vec![true, true, true, false, true]).slice(1, 3));
623 let case2 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
624 .len(3)
625 .offset(1)
626 .nulls(Some(struct_nulls.clone()))
627 .add_child_data(int_data.clone())
628 .build()
629 .unwrap();
630
631 let offset_int_data = int_data.slice(1, 4);
633 let case3 = ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
634 .len(3)
635 .nulls(Some(struct_nulls))
636 .add_child_data(offset_int_data)
637 .build()
638 .unwrap();
639
640 let expected = StructArray::new(
641 Fields::from(vec![int_field.clone()]),
642 vec![Arc::new(int_arr)],
643 Some(NullBuffer::new(BooleanBuffer::from(vec![
644 true, true, true, false, true,
645 ]))),
646 )
647 .slice(1, 3);
648
649 for case in [case1, case2, case3] {
650 let struct_arr_from_data = StructArray::from(case);
651 assert_eq!(struct_arr_from_data, expected);
652 assert_eq!(struct_arr_from_data.column(0), expected.column(0));
653 }
654 }
655
656 #[test]
657 #[should_panic(expected = "assertion failed: (offset + length) <= self.len()")]
658 fn test_struct_array_from_data_with_offset_and_length_error() {
659 let int_arr = Int32Array::from(vec![1, 2, 3, 4, 5]);
660 let int_field = Field::new("x", DataType::Int32, false);
661 let struct_nulls = NullBuffer::new(BooleanBuffer::from(vec![true, true, false]));
662 let int_data = int_arr.to_data();
663 let struct_data =
665 ArrayData::builder(DataType::Struct(Fields::from(vec![int_field.clone()])))
666 .len(3)
667 .offset(3)
668 .nulls(Some(struct_nulls))
669 .add_child_data(int_data)
670 .build()
671 .unwrap();
672 let _ = StructArray::from(struct_data);
673 }
674
675 #[test]
677 fn test_struct_array_index_access() {
678 let boolean = Arc::new(BooleanArray::from(vec![false, false, true, true]));
679 let int = Arc::new(Int32Array::from(vec![42, 28, 19, 31]));
680
681 let struct_array = StructArray::from(vec![
682 (
683 Arc::new(Field::new("b", DataType::Boolean, false)),
684 boolean.clone() as ArrayRef,
685 ),
686 (
687 Arc::new(Field::new("c", DataType::Int32, false)),
688 int.clone() as ArrayRef,
689 ),
690 ]);
691 assert_eq!(struct_array["b"].as_ref(), boolean.as_ref());
692 assert_eq!(struct_array["c"].as_ref(), int.as_ref());
693 }
694
695 #[test]
697 fn test_struct_array_from_vec() {
698 let strings: ArrayRef = Arc::new(StringArray::from(vec![
699 Some("joe"),
700 None,
701 None,
702 Some("mark"),
703 ]));
704 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
705
706 let arr =
707 StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())]).unwrap();
708
709 let struct_data = arr.into_data();
710 assert_eq!(4, struct_data.len());
711 assert_eq!(0, struct_data.null_count());
712
713 let expected_string_data = ArrayData::builder(DataType::Utf8)
714 .len(4)
715 .null_bit_buffer(Some(Buffer::from(&[9_u8])))
716 .add_buffer(Buffer::from([0, 3, 3, 3, 7].to_byte_slice()))
717 .add_buffer(Buffer::from(b"joemark"))
718 .build()
719 .unwrap();
720
721 let expected_int_data = ArrayData::builder(DataType::Int32)
722 .len(4)
723 .null_bit_buffer(Some(Buffer::from(&[11_u8])))
724 .add_buffer(Buffer::from([1, 2, 0, 4].to_byte_slice()))
725 .build()
726 .unwrap();
727
728 assert_eq!(expected_string_data, struct_data.child_data()[0]);
729 assert_eq!(expected_int_data, struct_data.child_data()[1]);
730 }
731
732 #[test]
733 fn test_struct_array_from_vec_error() {
734 let strings: ArrayRef = Arc::new(StringArray::from(vec![
735 Some("joe"),
736 None,
737 None,
738 ]));
740 let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)]));
741
742 let err = StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())])
743 .unwrap_err()
744 .to_string();
745
746 assert_eq!(
747 err,
748 "Invalid argument error: Incorrect array length for StructArray field \"f2\", expected 3 got 4"
749 )
750 }
751
752 #[test]
753 #[should_panic(
754 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
755 )]
756 fn test_struct_array_from_mismatched_types_single() {
757 drop(StructArray::from(vec![(
758 Arc::new(Field::new("b", DataType::Int16, false)),
759 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
760 )]));
761 }
762
763 #[test]
764 #[should_panic(
765 expected = "Incorrect datatype for StructArray field \\\"b\\\", expected Int16 got Boolean"
766 )]
767 fn test_struct_array_from_mismatched_types_multiple() {
768 drop(StructArray::from(vec![
769 (
770 Arc::new(Field::new("b", DataType::Int16, false)),
771 Arc::new(BooleanArray::from(vec![false, false, true, true])) as Arc<dyn Array>,
772 ),
773 (
774 Arc::new(Field::new("c", DataType::Utf8, false)),
775 Arc::new(Int32Array::from(vec![42, 28, 19, 31])),
776 ),
777 ]));
778 }
779
780 #[test]
781 fn test_struct_array_slice() {
782 let boolean_data = ArrayData::builder(DataType::Boolean)
783 .len(5)
784 .add_buffer(Buffer::from([0b00010000]))
785 .null_bit_buffer(Some(Buffer::from([0b00010001])))
786 .build()
787 .unwrap();
788 let int_data = ArrayData::builder(DataType::Int32)
789 .len(5)
790 .add_buffer(Buffer::from([0, 28, 42, 0, 0].to_byte_slice()))
791 .null_bit_buffer(Some(Buffer::from([0b00000110])))
792 .build()
793 .unwrap();
794
795 let field_types = vec![
796 Field::new("a", DataType::Boolean, true),
797 Field::new("b", DataType::Int32, true),
798 ];
799 let struct_array_data = ArrayData::builder(DataType::Struct(field_types.into()))
800 .len(5)
801 .add_child_data(boolean_data.clone())
802 .add_child_data(int_data.clone())
803 .null_bit_buffer(Some(Buffer::from([0b00010111])))
804 .build()
805 .unwrap();
806 let struct_array = StructArray::from(struct_array_data);
807
808 assert_eq!(5, struct_array.len());
809 assert_eq!(1, struct_array.null_count());
810 assert!(struct_array.is_valid(0));
811 assert!(struct_array.is_valid(1));
812 assert!(struct_array.is_valid(2));
813 assert!(struct_array.is_null(3));
814 assert!(struct_array.is_valid(4));
815 assert_eq!(boolean_data, struct_array.column(0).to_data());
816 assert_eq!(int_data, struct_array.column(1).to_data());
817
818 let c0 = struct_array.column(0);
819 let c0 = c0.as_any().downcast_ref::<BooleanArray>().unwrap();
820 assert_eq!(5, c0.len());
821 assert_eq!(3, c0.null_count());
822 assert!(c0.is_valid(0));
823 assert!(!c0.value(0));
824 assert!(c0.is_null(1));
825 assert!(c0.is_null(2));
826 assert!(c0.is_null(3));
827 assert!(c0.is_valid(4));
828 assert!(c0.value(4));
829
830 let c1 = struct_array.column(1);
831 let c1 = c1.as_any().downcast_ref::<Int32Array>().unwrap();
832 assert_eq!(5, c1.len());
833 assert_eq!(3, c1.null_count());
834 assert!(c1.is_null(0));
835 assert!(c1.is_valid(1));
836 assert_eq!(28, c1.value(1));
837 assert!(c1.is_valid(2));
838 assert_eq!(42, c1.value(2));
839 assert!(c1.is_null(3));
840 assert!(c1.is_null(4));
841
842 let sliced_array = struct_array.slice(2, 3);
843 let sliced_array = sliced_array.as_any().downcast_ref::<StructArray>().unwrap();
844 assert_eq!(3, sliced_array.len());
845 assert_eq!(1, sliced_array.null_count());
846 assert!(sliced_array.is_valid(0));
847 assert!(sliced_array.is_null(1));
848 assert!(sliced_array.is_valid(2));
849
850 let sliced_c0 = sliced_array.column(0);
851 let sliced_c0 = sliced_c0.as_any().downcast_ref::<BooleanArray>().unwrap();
852 assert_eq!(3, sliced_c0.len());
853 assert!(sliced_c0.is_null(0));
854 assert!(sliced_c0.is_null(1));
855 assert!(sliced_c0.is_valid(2));
856 assert!(sliced_c0.value(2));
857
858 let sliced_c1 = sliced_array.column(1);
859 let sliced_c1 = sliced_c1.as_any().downcast_ref::<Int32Array>().unwrap();
860 assert_eq!(3, sliced_c1.len());
861 assert!(sliced_c1.is_valid(0));
862 assert_eq!(42, sliced_c1.value(0));
863 assert!(sliced_c1.is_null(1));
864 assert!(sliced_c1.is_null(2));
865 }
866
867 #[test]
868 #[should_panic(
869 expected = "Incorrect array length for StructArray field \\\"c\\\", expected 1 got 2"
870 )]
871 fn test_invalid_struct_child_array_lengths() {
872 drop(StructArray::from(vec![
873 (
874 Arc::new(Field::new("b", DataType::Float32, false)),
875 Arc::new(Float32Array::from(vec![1.1])) as Arc<dyn Array>,
876 ),
877 (
878 Arc::new(Field::new("c", DataType::Float64, false)),
879 Arc::new(Float64Array::from(vec![2.2, 3.3])),
880 ),
881 ]));
882 }
883
884 #[test]
885 #[should_panic(expected = "use StructArray::try_new_with_length")]
886 fn test_struct_array_from_empty() {
887 let _ = StructArray::from(vec![]);
890 }
891
892 #[test]
893 fn test_empty_struct_array() {
894 assert!(StructArray::try_new(Fields::empty(), vec![], None).is_err());
895
896 let arr = StructArray::new_empty_fields(10, None);
897 assert_eq!(arr.len(), 10);
898 assert_eq!(arr.null_count(), 0);
899 assert_eq!(arr.num_columns(), 0);
900
901 let arr2 = StructArray::try_new_with_length(Fields::empty(), vec![], None, 10).unwrap();
902 assert_eq!(arr2.len(), 10);
903
904 let arr = StructArray::new_empty_fields(10, Some(NullBuffer::new_null(10)));
905 assert_eq!(arr.len(), 10);
906 assert_eq!(arr.null_count(), 10);
907 assert_eq!(arr.num_columns(), 0);
908
909 let arr2 = StructArray::try_new_with_length(
910 Fields::empty(),
911 vec![],
912 Some(NullBuffer::new_null(10)),
913 10,
914 )
915 .unwrap();
916 assert_eq!(arr2.len(), 10);
917 }
918
919 #[test]
920 #[should_panic(expected = "Found unmasked nulls for non-nullable StructArray field \\\"c\\\"")]
921 fn test_struct_array_from_mismatched_nullability() {
922 drop(StructArray::from(vec![(
923 Arc::new(Field::new("c", DataType::Int32, false)),
924 Arc::new(Int32Array::from(vec![Some(42), None, Some(19)])) as ArrayRef,
925 )]));
926 }
927
928 #[test]
929 fn test_struct_array_fmt_debug() {
930 let arr: StructArray = StructArray::new(
931 vec![Arc::new(Field::new("c", DataType::Int32, true))].into(),
932 vec![Arc::new(Int32Array::from((0..30).collect::<Vec<_>>())) as ArrayRef],
933 Some(NullBuffer::new(BooleanBuffer::from(
934 (0..30).map(|i| i % 2 == 0).collect::<Vec<_>>(),
935 ))),
936 );
937 assert_eq!(
938 format!("{arr:?}"),
939 "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]"
940 )
941 }
942
943 #[test]
944 fn test_struct_array_logical_nulls() {
945 let field = Field::new("a", DataType::Int32, false);
947 let values = vec![1, 2, 3];
948 let nulls = NullBuffer::from(vec![true, true, true]);
950 let array = Int32Array::new(values.into(), Some(nulls));
951 let child = Arc::new(array) as ArrayRef;
952 assert!(child.logical_nulls().is_some());
953 assert_eq!(child.logical_nulls().unwrap().null_count(), 0);
954
955 let fields = Fields::from(vec![field]);
956 let arrays = vec![child];
957 let nulls = None;
958
959 StructArray::try_new(fields, arrays, nulls).expect("should not error");
960 }
961}