1use crate::take::take;
21use arrow_array::{
22 Array, ArrayRef, BooleanArray, Int32Array, Scalar, UnionArray, make_array, new_empty_array,
23 new_null_array,
24};
25use arrow_buffer::{BooleanBuffer, MutableBuffer, NullBuffer, ScalarBuffer, bit_util};
26use arrow_data::layout;
27use arrow_schema::{ArrowError, DataType, UnionFields};
28use std::cmp::Ordering;
29use std::sync::Arc;
30
31pub fn union_extract(union_array: &UnionArray, target: &str) -> Result<ArrayRef, ArrowError> {
80 let fields = match union_array.data_type() {
81 DataType::Union(fields, _) => fields,
82 _ => unreachable!(),
83 };
84
85 let (target_type_id, _) = fields
86 .iter()
87 .find(|field| field.1.name() == target)
88 .ok_or_else(|| {
89 ArrowError::InvalidArgumentError(format!("field {target} not found on union"))
90 })?;
91
92 union_extract_impl(union_array, fields, target_type_id)
93}
94
95pub fn union_extract_by_id(
104 union_array: &UnionArray,
105 target_type_id: i8,
106) -> Result<ArrayRef, ArrowError> {
107 let fields = match union_array.data_type() {
108 DataType::Union(fields, _) => fields,
109 _ => unreachable!(),
110 };
111
112 if fields.iter().all(|(id, _)| id != target_type_id) {
113 return Err(ArrowError::InvalidArgumentError(format!(
114 "type_id {target_type_id} not found on union"
115 )));
116 }
117
118 union_extract_impl(union_array, fields, target_type_id)
119}
120
121fn union_extract_impl(
122 union_array: &UnionArray,
123 fields: &UnionFields,
124 target_type_id: i8,
125) -> Result<ArrayRef, ArrowError> {
126 match union_array.offsets() {
127 Some(_) => extract_dense(union_array, fields, target_type_id),
128 None => extract_sparse(union_array, fields, target_type_id),
129 }
130}
131
132fn extract_sparse(
133 union_array: &UnionArray,
134 fields: &UnionFields,
135 target_type_id: i8,
136) -> Result<ArrayRef, ArrowError> {
137 let target = union_array.child(target_type_id);
138
139 if fields.len() == 1 || union_array.is_empty() || target.null_count() == target.len() || target.data_type().is_null()
142 {
144 Ok(Arc::clone(target))
145 } else {
146 match eq_scalar(union_array.type_ids(), target_type_id) {
147 BoolValue::Scalar(true) => Ok(Arc::clone(target)),
149 BoolValue::Scalar(false) => {
151 if layout(target.data_type()).can_contain_null_mask {
152 let data = unsafe {
155 target
156 .into_data()
157 .into_builder()
158 .nulls(Some(NullBuffer::new_null(target.len())))
159 .build_unchecked()
160 };
161
162 Ok(make_array(data))
163 } else {
164 Ok(new_null_array(target.data_type(), target.len()))
166 }
167 }
168 BoolValue::Buffer(selected) => {
170 if layout(target.data_type()).can_contain_null_mask {
171 let nulls = match target.nulls().filter(|n| n.null_count() > 0) {
173 Some(nulls) => &selected & nulls.inner(),
176 None => selected,
178 };
179
180 let data = unsafe {
182 assert_eq!(nulls.len(), target.len());
183
184 target
185 .into_data()
186 .into_builder()
187 .nulls(Some(nulls.into()))
188 .build_unchecked()
189 };
190
191 Ok(make_array(data))
192 } else {
193 Ok(crate::zip::zip(
195 &BooleanArray::new(selected, None),
196 target,
197 &Scalar::new(new_null_array(target.data_type(), 1)),
198 )?)
199 }
200 }
201 }
202 }
203}
204
205fn extract_dense(
206 union_array: &UnionArray,
207 fields: &UnionFields,
208 target_type_id: i8,
209) -> Result<ArrayRef, ArrowError> {
210 let target = union_array.child(target_type_id);
211 let offsets = union_array.offsets().unwrap();
212
213 if union_array.is_empty() {
214 if target.is_empty() {
216 Ok(Arc::clone(target))
218 } else {
219 Ok(new_empty_array(target.data_type()))
221 }
222 } else if target.is_empty() {
223 Ok(new_null_array(target.data_type(), union_array.len()))
225 } else if target.null_count() == target.len() || target.data_type().is_null() {
226 match target.len().cmp(&union_array.len()) {
228 Ordering::Less => Ok(new_null_array(target.data_type(), union_array.len())),
230 Ordering::Equal => Ok(Arc::clone(target)),
232 Ordering::Greater => Ok(target.slice(0, union_array.len())),
234 }
235 } else if fields.len() == 1 || fields
237 .iter()
238 .filter(|(field_type_id, _)| *field_type_id != target_type_id)
239 .all(|(sibling_type_id, _)| union_array.child(sibling_type_id).is_empty())
240 {
242 Ok(extract_dense_all_selected(union_array, target, offsets)?)
244 } else {
245 match eq_scalar(union_array.type_ids(), target_type_id) {
246 BoolValue::Scalar(true) => {
250 Ok(extract_dense_all_selected(union_array, target, offsets)?)
251 }
252 BoolValue::Scalar(false) => {
253 match (target.len().cmp(&union_array.len()), layout(target.data_type()).can_contain_null_mask) {
257 (Ordering::Less, _) | (_, false) => { Ok(new_null_array(target.data_type(), union_array.len()))
260 }
261 (Ordering::Equal, true) => {
263 let data = unsafe {
265 target
266 .into_data()
267 .into_builder()
268 .nulls(Some(NullBuffer::new_null(union_array.len())))
269 .build_unchecked()
270 };
271
272 Ok(make_array(data))
273 }
274 (Ordering::Greater, true) => {
276 let data = unsafe {
278 target
279 .into_data()
280 .slice(0, union_array.len())
281 .into_builder()
282 .nulls(Some(NullBuffer::new_null(union_array.len())))
283 .build_unchecked()
284 };
285
286 Ok(make_array(data))
287 }
288 }
289 }
290 BoolValue::Buffer(selected) => {
291 Ok(take(
293 target,
294 &Int32Array::try_new(offsets.clone(), Some(selected.into()))?,
295 None,
296 )?)
297 }
298 }
299 }
300}
301
302fn extract_dense_all_selected(
303 union_array: &UnionArray,
304 target: &Arc<dyn Array>,
305 offsets: &ScalarBuffer<i32>,
306) -> Result<ArrayRef, ArrowError> {
307 let sequential =
308 target.len() - offsets[0] as usize >= union_array.len() && is_sequential(offsets);
309
310 if sequential && target.len() == union_array.len() {
311 Ok(Arc::clone(target))
313 } else if sequential && target.len() > union_array.len() {
314 Ok(target.slice(offsets[0] as usize, union_array.len()))
316 } else {
317 let indices = Int32Array::try_new(offsets.clone(), None)?;
319
320 Ok(take(target, &indices, None)?)
321 }
322}
323
324const EQ_SCALAR_CHUNK_SIZE: usize = 512;
325
326#[derive(Debug, PartialEq)]
328enum BoolValue {
329 Scalar(bool),
332 Buffer(BooleanBuffer),
334}
335
336fn eq_scalar(type_ids: &[i8], target: i8) -> BoolValue {
337 eq_scalar_inner(EQ_SCALAR_CHUNK_SIZE, type_ids, target)
338}
339
340fn count_first_run(chunk_size: usize, type_ids: &[i8], mut f: impl FnMut(i8) -> bool) -> usize {
341 type_ids
342 .chunks(chunk_size)
343 .take_while(|chunk| chunk.iter().copied().fold(true, |b, v| b & f(v)))
344 .map(|chunk| chunk.len())
345 .sum()
346}
347
348fn eq_scalar_inner(chunk_size: usize, type_ids: &[i8], target: i8) -> BoolValue {
350 let true_bits = count_first_run(chunk_size, type_ids, |v| v == target);
351
352 let (set_bits, val) = if true_bits == type_ids.len() {
353 return BoolValue::Scalar(true);
354 } else if true_bits == 0 {
355 let false_bits = count_first_run(chunk_size, type_ids, |v| v != target);
356
357 if false_bits == type_ids.len() {
358 return BoolValue::Scalar(false);
359 } else {
360 (false_bits, false)
361 }
362 } else {
363 (true_bits, true)
364 };
365
366 let set_bits = set_bits - set_bits % 64;
368
369 let mut buffer =
370 MutableBuffer::new(bit_util::ceil(type_ids.len(), 8)).with_bitset(set_bits / 8, val);
371
372 buffer.extend(type_ids[set_bits..].chunks(64).map(|chunk| {
373 chunk
374 .iter()
375 .copied()
376 .enumerate()
377 .fold(0, |packed, (bit_idx, v)| {
378 packed | (((v == target) as u64) << bit_idx)
379 })
380 }));
381
382 BoolValue::Buffer(BooleanBuffer::new(buffer.into(), 0, type_ids.len()))
383}
384
385const IS_SEQUENTIAL_CHUNK_SIZE: usize = 64;
386
387fn is_sequential(offsets: &[i32]) -> bool {
388 is_sequential_generic::<IS_SEQUENTIAL_CHUNK_SIZE>(offsets)
389}
390
391fn is_sequential_generic<const N: usize>(offsets: &[i32]) -> bool {
392 if offsets.is_empty() {
393 return true;
394 }
395
396 if offsets[0] + offsets.len() as i32 - 1 != offsets[offsets.len() - 1] {
406 return false;
407 }
408
409 let chunks = offsets.chunks_exact(N);
410
411 let remainder = chunks.remainder();
412
413 chunks.enumerate().all(|(i, chunk)| {
414 let chunk_array = <&[i32; N]>::try_from(chunk).unwrap();
415
416 chunk_array
418 .iter()
419 .copied()
420 .enumerate()
421 .fold(true, |acc, (i, offset)| {
422 acc & (offset == chunk_array[0] + i as i32)
423 })
424 && offsets[0] + (i * N) as i32 == chunk_array[0] }) && remainder
426 .iter()
427 .copied()
428 .enumerate()
429 .fold(true, |acc, (i, offset)| {
430 acc & (offset == remainder[0] + i as i32)
431 }) }
433
434#[cfg(test)]
435mod tests {
436 use super::{
437 BoolValue, eq_scalar_inner, is_sequential_generic, union_extract, union_extract_by_id,
438 };
439 use arrow_array::{Array, Int32Array, NullArray, StringArray, UnionArray, new_null_array};
440 use arrow_buffer::{BooleanBuffer, ScalarBuffer};
441 use arrow_schema::{ArrowError, DataType, Field, UnionFields, UnionMode};
442 use std::sync::Arc;
443
444 #[test]
445 #[cfg_attr(miri, ignore)] fn test_eq_scalar() {
447 const ARRAY_LEN: usize = 64 * 4;
450
451 const EQ_SCALAR_CHUNK_SIZE: usize = 3;
453
454 fn eq_scalar(type_ids: &[i8], target: i8) -> BoolValue {
455 eq_scalar_inner(EQ_SCALAR_CHUNK_SIZE, type_ids, target)
456 }
457
458 fn cross_check(left: &[i8], right: i8) -> BooleanBuffer {
459 BooleanBuffer::collect_bool(left.len(), |i| left[i] == right)
460 }
461
462 assert_eq!(eq_scalar(&[], 1), BoolValue::Scalar(true));
463
464 assert_eq!(eq_scalar(&[1], 1), BoolValue::Scalar(true));
465 assert_eq!(eq_scalar(&[2], 1), BoolValue::Scalar(false));
466
467 let mut values = [1; ARRAY_LEN];
468
469 assert_eq!(eq_scalar(&values, 1), BoolValue::Scalar(true));
470 assert_eq!(eq_scalar(&values, 2), BoolValue::Scalar(false));
471
472 for i in 1..ARRAY_LEN {
474 assert_eq!(eq_scalar(&values[..i], 1), BoolValue::Scalar(true));
475 assert_eq!(eq_scalar(&values[..i], 2), BoolValue::Scalar(false));
476 }
477
478 for i in 0..ARRAY_LEN {
480 values[i] = 2;
481
482 assert_eq!(
483 eq_scalar(&values, 1),
484 BoolValue::Buffer(cross_check(&values, 1))
485 );
486 assert_eq!(
487 eq_scalar(&values, 2),
488 BoolValue::Buffer(cross_check(&values, 2))
489 );
490
491 values[i] = 1;
492 }
493 }
494
495 #[test]
496 fn test_is_sequential() {
497 const CHUNK_SIZE: usize = 3;
503 fn is_sequential(v: &[i32]) -> bool {
510 is_sequential_generic::<CHUNK_SIZE>(v)
511 }
512
513 assert!(is_sequential(&[])); assert!(is_sequential(&[1])); assert!(is_sequential(&[1, 2]));
517 assert!(is_sequential(&[1, 2, 3]));
518 assert!(is_sequential(&[1, 2, 3, 4]));
519 assert!(is_sequential(&[1, 2, 3, 4, 5]));
520 assert!(is_sequential(&[1, 2, 3, 4, 5, 6]));
521 assert!(is_sequential(&[1, 2, 3, 4, 5, 6, 7]));
522 assert!(is_sequential(&[1, 2, 3, 4, 5, 6, 7, 8]));
523
524 assert!(!is_sequential(&[8, 7]));
525 assert!(!is_sequential(&[8, 7, 6]));
526 assert!(!is_sequential(&[8, 7, 6, 5]));
527 assert!(!is_sequential(&[8, 7, 6, 5, 4]));
528 assert!(!is_sequential(&[8, 7, 6, 5, 4, 3]));
529 assert!(!is_sequential(&[8, 7, 6, 5, 4, 3, 2]));
530 assert!(!is_sequential(&[8, 7, 6, 5, 4, 3, 2, 1]));
531
532 assert!(!is_sequential(&[0, 2]));
533 assert!(!is_sequential(&[1, 0]));
534
535 assert!(!is_sequential(&[0, 2, 3]));
536 assert!(!is_sequential(&[1, 0, 3]));
537 assert!(!is_sequential(&[1, 2, 0]));
538
539 assert!(!is_sequential(&[0, 2, 3, 4]));
540 assert!(!is_sequential(&[1, 0, 3, 4]));
541 assert!(!is_sequential(&[1, 2, 0, 4]));
542 assert!(!is_sequential(&[1, 2, 3, 0]));
543
544 assert!(!is_sequential(&[0, 2, 3, 4, 5]));
545 assert!(!is_sequential(&[1, 0, 3, 4, 5]));
546 assert!(!is_sequential(&[1, 2, 0, 4, 5]));
547 assert!(!is_sequential(&[1, 2, 3, 0, 5]));
548 assert!(!is_sequential(&[1, 2, 3, 4, 0]));
549
550 assert!(!is_sequential(&[0, 2, 3, 4, 5, 6]));
551 assert!(!is_sequential(&[1, 0, 3, 4, 5, 6]));
552 assert!(!is_sequential(&[1, 2, 0, 4, 5, 6]));
553 assert!(!is_sequential(&[1, 2, 3, 0, 5, 6]));
554 assert!(!is_sequential(&[1, 2, 3, 4, 0, 6]));
555 assert!(!is_sequential(&[1, 2, 3, 4, 5, 0]));
556
557 assert!(!is_sequential(&[0, 2, 3, 4, 5, 6, 7]));
558 assert!(!is_sequential(&[1, 0, 3, 4, 5, 6, 7]));
559 assert!(!is_sequential(&[1, 2, 0, 4, 5, 6, 7]));
560 assert!(!is_sequential(&[1, 2, 3, 0, 5, 6, 7]));
561 assert!(!is_sequential(&[1, 2, 3, 4, 0, 6, 7]));
562 assert!(!is_sequential(&[1, 2, 3, 4, 5, 0, 7]));
563 assert!(!is_sequential(&[1, 2, 3, 4, 5, 6, 0]));
564
565 assert!(!is_sequential(&[0, 2, 3, 4, 5, 6, 7, 8]));
566 assert!(!is_sequential(&[1, 0, 3, 4, 5, 6, 7, 8]));
567 assert!(!is_sequential(&[1, 2, 0, 4, 5, 6, 7, 8]));
568 assert!(!is_sequential(&[1, 2, 3, 0, 5, 6, 7, 8]));
569 assert!(!is_sequential(&[1, 2, 3, 4, 0, 6, 7, 8]));
570 assert!(!is_sequential(&[1, 2, 3, 4, 5, 0, 7, 8]));
571 assert!(!is_sequential(&[1, 2, 3, 4, 5, 6, 0, 8]));
572 assert!(!is_sequential(&[1, 2, 3, 4, 5, 6, 7, 0]));
573
574 assert!(!is_sequential(&[1, 2, 3, 5]));
576 assert!(!is_sequential(&[1, 2, 3, 5, 6]));
577 assert!(!is_sequential(&[1, 2, 3, 5, 6, 7]));
578 assert!(!is_sequential(&[1, 2, 3, 4, 5, 6, 8]));
579 assert!(!is_sequential(&[1, 2, 3, 4, 5, 6, 8, 9]));
580 }
581
582 fn str1() -> UnionFields {
583 UnionFields::try_new(vec![1], vec![Field::new("str", DataType::Utf8, true)]).unwrap()
584 }
585
586 fn str1_int3() -> UnionFields {
587 UnionFields::try_new(
588 vec![1, 3],
589 vec![
590 Field::new("str", DataType::Utf8, true),
591 Field::new("int", DataType::Int32, true),
592 ],
593 )
594 .unwrap()
595 }
596
597 #[test]
598 fn sparse_1_1_single_field() {
599 let union = UnionArray::try_new(
600 str1(),
602 ScalarBuffer::from(vec![1, 1]), None, vec![
605 Arc::new(StringArray::from(vec!["a", "b"])), ],
607 )
608 .unwrap();
609
610 let expected = StringArray::from(vec!["a", "b"]);
611 let extracted = union_extract(&union, "str").unwrap();
612
613 assert_eq!(extracted.into_data(), expected.into_data());
614 }
615
616 #[test]
617 fn sparse_1_2_empty() {
618 let union = UnionArray::try_new(
619 str1_int3(),
621 ScalarBuffer::from(vec![]), None, vec![
624 Arc::new(StringArray::new_null(0)),
625 Arc::new(Int32Array::new_null(0)),
626 ],
627 )
628 .unwrap();
629
630 let expected = StringArray::new_null(0);
631 let extracted = union_extract(&union, "str").unwrap(); assert_eq!(extracted.into_data(), expected.into_data());
634 }
635
636 #[test]
637 fn sparse_1_3a_null_target() {
638 let union = UnionArray::try_new(
639 UnionFields::try_new(
641 vec![1, 3],
642 vec![
643 Field::new("str", DataType::Utf8, true),
644 Field::new("null", DataType::Null, true), ],
646 )
647 .unwrap(),
648 ScalarBuffer::from(vec![1]), None, vec![
651 Arc::new(StringArray::new_null(1)),
652 Arc::new(NullArray::new(1)), ],
654 )
655 .unwrap();
656
657 let expected = NullArray::new(1);
658 let extracted = union_extract(&union, "null").unwrap();
659
660 assert_eq!(extracted.into_data(), expected.into_data());
661 }
662
663 #[test]
664 fn sparse_1_3b_null_target() {
665 let union = UnionArray::try_new(
666 str1_int3(),
668 ScalarBuffer::from(vec![1]), None, vec![
671 Arc::new(StringArray::new_null(1)), Arc::new(Int32Array::new_null(1)),
673 ],
674 )
675 .unwrap();
676
677 let expected = StringArray::new_null(1);
678 let extracted = union_extract(&union, "str").unwrap(); assert_eq!(extracted.into_data(), expected.into_data());
681 }
682
683 #[test]
684 fn sparse_2_all_types_match() {
685 let union = UnionArray::try_new(
686 str1_int3(),
688 ScalarBuffer::from(vec![3, 3]), None, vec![
691 Arc::new(StringArray::new_null(2)),
692 Arc::new(Int32Array::from(vec![1, 4])), ],
694 )
695 .unwrap();
696
697 let expected = Int32Array::from(vec![1, 4]);
698 let extracted = union_extract(&union, "int").unwrap();
699
700 assert_eq!(extracted.into_data(), expected.into_data());
701 }
702
703 #[test]
704 fn sparse_3_1_none_match_target_can_contain_null_mask() {
705 let union = UnionArray::try_new(
706 str1_int3(),
708 ScalarBuffer::from(vec![1, 1, 1, 1]), None, vec![
711 Arc::new(StringArray::new_null(4)),
712 Arc::new(Int32Array::from(vec![None, Some(4), None, Some(8)])), ],
714 )
715 .unwrap();
716
717 let expected = Int32Array::new_null(4);
718 let extracted = union_extract(&union, "int").unwrap();
719
720 assert_eq!(extracted.into_data(), expected.into_data());
721 }
722
723 fn str1_union3(union3_datatype: DataType) -> UnionFields {
724 UnionFields::try_new(
725 vec![1, 3],
726 vec![
727 Field::new("str", DataType::Utf8, true),
728 Field::new("union", union3_datatype, true),
729 ],
730 )
731 .unwrap()
732 }
733
734 #[test]
735 fn sparse_3_2_none_match_cant_contain_null_mask_union_target() {
736 let target_fields = str1();
737 let target_type = DataType::Union(target_fields.clone(), UnionMode::Sparse);
738
739 let union = UnionArray::try_new(
740 str1_union3(target_type.clone()),
742 ScalarBuffer::from(vec![1, 1]), None, vec![
745 Arc::new(StringArray::new_null(2)),
746 Arc::new(
748 UnionArray::try_new(
749 target_fields.clone(),
750 ScalarBuffer::from(vec![1, 1]),
751 None,
752 vec![Arc::new(StringArray::from(vec!["a", "b"]))],
753 )
754 .unwrap(),
755 ),
756 ],
757 )
758 .unwrap();
759
760 let expected = new_null_array(&target_type, 2);
761 let extracted = union_extract(&union, "union").unwrap();
762
763 assert_eq!(extracted.into_data(), expected.into_data());
764 }
765
766 #[test]
767 fn sparse_4_1_1_target_with_nulls() {
768 let union = UnionArray::try_new(
769 str1_int3(),
771 ScalarBuffer::from(vec![3, 3, 1, 1]), None, vec![
774 Arc::new(StringArray::new_null(4)),
775 Arc::new(Int32Array::from(vec![None, Some(4), None, Some(8)])), ],
777 )
778 .unwrap();
779
780 let expected = Int32Array::from(vec![None, Some(4), None, None]);
781 let extracted = union_extract(&union, "int").unwrap();
782
783 assert_eq!(extracted.into_data(), expected.into_data());
784 }
785
786 #[test]
787 fn sparse_4_1_2_target_without_nulls() {
788 let union = UnionArray::try_new(
789 str1_int3(),
791 ScalarBuffer::from(vec![1, 3, 3]), None, vec![
794 Arc::new(StringArray::new_null(3)),
795 Arc::new(Int32Array::from(vec![2, 4, 8])), ],
797 )
798 .unwrap();
799
800 let expected = Int32Array::from(vec![None, Some(4), Some(8)]);
801 let extracted = union_extract(&union, "int").unwrap();
802
803 assert_eq!(extracted.into_data(), expected.into_data());
804 }
805
806 #[test]
807 fn sparse_4_2_some_match_target_cant_contain_null_mask() {
808 let target_fields = str1();
809 let target_type = DataType::Union(target_fields.clone(), UnionMode::Sparse);
810
811 let union = UnionArray::try_new(
812 str1_union3(target_type),
814 ScalarBuffer::from(vec![3, 1]), None, vec![
817 Arc::new(StringArray::new_null(2)),
818 Arc::new(
819 UnionArray::try_new(
820 target_fields.clone(),
821 ScalarBuffer::from(vec![1, 1]),
822 None,
823 vec![Arc::new(StringArray::from(vec!["a", "b"]))],
824 )
825 .unwrap(),
826 ),
827 ],
828 )
829 .unwrap();
830
831 let expected = UnionArray::try_new(
832 target_fields,
833 ScalarBuffer::from(vec![1, 1]),
834 None,
835 vec![Arc::new(StringArray::from(vec![Some("a"), None]))],
836 )
837 .unwrap();
838 let extracted = union_extract(&union, "union").unwrap();
839
840 assert_eq!(extracted.into_data(), expected.into_data());
841 }
842
843 #[test]
844 fn dense_1_1_both_empty() {
845 let union = UnionArray::try_new(
846 str1_int3(),
847 ScalarBuffer::from(vec![]), Some(ScalarBuffer::from(vec![])), vec![
850 Arc::new(StringArray::new_null(0)), Arc::new(Int32Array::new_null(0)),
852 ],
853 )
854 .unwrap();
855
856 let expected = StringArray::new_null(0);
857 let extracted = union_extract(&union, "str").unwrap();
858
859 assert_eq!(extracted.into_data(), expected.into_data());
860 }
861
862 #[test]
863 fn dense_1_2_empty_union_target_non_empty() {
864 let union = UnionArray::try_new(
865 str1_int3(),
866 ScalarBuffer::from(vec![]), Some(ScalarBuffer::from(vec![])), vec![
869 Arc::new(StringArray::new_null(1)), Arc::new(Int32Array::new_null(0)),
871 ],
872 )
873 .unwrap();
874
875 let expected = StringArray::new_null(0);
876 let extracted = union_extract(&union, "str").unwrap();
877
878 assert_eq!(extracted.into_data(), expected.into_data());
879 }
880
881 #[test]
882 fn dense_2_non_empty_union_target_empty() {
883 let union = UnionArray::try_new(
884 str1_int3(),
885 ScalarBuffer::from(vec![3, 3]), Some(ScalarBuffer::from(vec![0, 1])), vec![
888 Arc::new(StringArray::new_null(0)), Arc::new(Int32Array::new_null(2)),
890 ],
891 )
892 .unwrap();
893
894 let expected = StringArray::new_null(2);
895 let extracted = union_extract(&union, "str").unwrap();
896
897 assert_eq!(extracted.into_data(), expected.into_data());
898 }
899
900 #[test]
901 fn dense_3_1_null_target_smaller_len() {
902 let union = UnionArray::try_new(
903 str1_int3(),
904 ScalarBuffer::from(vec![3, 3]), Some(ScalarBuffer::from(vec![0, 0])), vec![
907 Arc::new(StringArray::new_null(1)), Arc::new(Int32Array::new_null(2)),
909 ],
910 )
911 .unwrap();
912
913 let expected = StringArray::new_null(2);
914 let extracted = union_extract(&union, "str").unwrap();
915
916 assert_eq!(extracted.into_data(), expected.into_data());
917 }
918
919 #[test]
920 fn dense_3_2_null_target_equal_len() {
921 let union = UnionArray::try_new(
922 str1_int3(),
923 ScalarBuffer::from(vec![3, 3]), Some(ScalarBuffer::from(vec![0, 0])), vec![
926 Arc::new(StringArray::new_null(2)), Arc::new(Int32Array::new_null(2)),
928 ],
929 )
930 .unwrap();
931
932 let expected = StringArray::new_null(2);
933 let extracted = union_extract(&union, "str").unwrap();
934
935 assert_eq!(extracted.into_data(), expected.into_data());
936 }
937
938 #[test]
939 fn dense_3_3_null_target_bigger_len() {
940 let union = UnionArray::try_new(
941 str1_int3(),
942 ScalarBuffer::from(vec![3, 3]), Some(ScalarBuffer::from(vec![0, 0])), vec![
945 Arc::new(StringArray::new_null(3)), Arc::new(Int32Array::new_null(3)),
947 ],
948 )
949 .unwrap();
950
951 let expected = StringArray::new_null(2);
952 let extracted = union_extract(&union, "str").unwrap();
953
954 assert_eq!(extracted.into_data(), expected.into_data());
955 }
956
957 #[test]
958 fn dense_4_1a_single_type_sequential_offsets_equal_len() {
959 let union = UnionArray::try_new(
960 str1(),
962 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
965 Arc::new(StringArray::from(vec!["a1", "b2"])), ],
967 )
968 .unwrap();
969
970 let expected = StringArray::from(vec!["a1", "b2"]);
971 let extracted = union_extract(&union, "str").unwrap();
972
973 assert_eq!(extracted.into_data(), expected.into_data());
974 }
975
976 #[test]
977 fn dense_4_2a_single_type_sequential_offsets_bigger() {
978 let union = UnionArray::try_new(
979 str1(),
981 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
984 Arc::new(StringArray::from(vec!["a1", "b2", "c3"])), ],
986 )
987 .unwrap();
988
989 let expected = StringArray::from(vec!["a1", "b2"]);
990 let extracted = union_extract(&union, "str").unwrap();
991
992 assert_eq!(extracted.into_data(), expected.into_data());
993 }
994
995 #[test]
996 fn dense_4_3a_single_type_non_sequential() {
997 let union = UnionArray::try_new(
998 str1(),
1000 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 2])), vec![
1003 Arc::new(StringArray::from(vec!["a1", "b2", "c3"])), ],
1005 )
1006 .unwrap();
1007
1008 let expected = StringArray::from(vec!["a1", "c3"]);
1009 let extracted = union_extract(&union, "str").unwrap();
1010
1011 assert_eq!(extracted.into_data(), expected.into_data());
1012 }
1013
1014 #[test]
1015 fn dense_4_1b_empty_siblings_sequential_equal_len() {
1016 let union = UnionArray::try_new(
1017 str1_int3(),
1019 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
1022 Arc::new(StringArray::from(vec!["a", "b"])), Arc::new(Int32Array::new_null(0)), ],
1025 )
1026 .unwrap();
1027
1028 let expected = StringArray::from(vec!["a", "b"]);
1029 let extracted = union_extract(&union, "str").unwrap();
1030
1031 assert_eq!(extracted.into_data(), expected.into_data());
1032 }
1033
1034 #[test]
1035 fn dense_4_2b_empty_siblings_sequential_bigger_len() {
1036 let union = UnionArray::try_new(
1037 str1_int3(),
1039 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
1042 Arc::new(StringArray::from(vec!["a", "b", "c"])), Arc::new(Int32Array::new_null(0)), ],
1045 )
1046 .unwrap();
1047
1048 let expected = StringArray::from(vec!["a", "b"]);
1049 let extracted = union_extract(&union, "str").unwrap();
1050
1051 assert_eq!(extracted.into_data(), expected.into_data());
1052 }
1053
1054 #[test]
1055 fn dense_4_3b_empty_sibling_non_sequential() {
1056 let union = UnionArray::try_new(
1057 str1_int3(),
1059 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 2])), vec![
1062 Arc::new(StringArray::from(vec!["a", "b", "c"])), Arc::new(Int32Array::new_null(0)), ],
1065 )
1066 .unwrap();
1067
1068 let expected = StringArray::from(vec!["a", "c"]);
1069 let extracted = union_extract(&union, "str").unwrap();
1070
1071 assert_eq!(extracted.into_data(), expected.into_data());
1072 }
1073
1074 #[test]
1075 fn dense_4_1c_all_types_match_sequential_equal_len() {
1076 let union = UnionArray::try_new(
1077 str1_int3(),
1079 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
1082 Arc::new(StringArray::from(vec!["a1", "b2"])), Arc::new(Int32Array::new_null(2)), ],
1085 )
1086 .unwrap();
1087
1088 let expected = StringArray::from(vec!["a1", "b2"]);
1089 let extracted = union_extract(&union, "str").unwrap();
1090
1091 assert_eq!(extracted.into_data(), expected.into_data());
1092 }
1093
1094 #[test]
1095 fn dense_4_2c_all_types_match_sequential_bigger_len() {
1096 let union = UnionArray::try_new(
1097 str1_int3(),
1099 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 1])), vec![
1102 Arc::new(StringArray::from(vec!["a1", "b2", "b3"])), Arc::new(Int32Array::new_null(2)), ],
1105 )
1106 .unwrap();
1107
1108 let expected = StringArray::from(vec!["a1", "b2"]);
1109 let extracted = union_extract(&union, "str").unwrap();
1110
1111 assert_eq!(extracted.into_data(), expected.into_data());
1112 }
1113
1114 #[test]
1115 fn dense_4_3c_all_types_match_non_sequential() {
1116 let union = UnionArray::try_new(
1117 str1_int3(),
1119 ScalarBuffer::from(vec![1, 1]), Some(ScalarBuffer::from(vec![0, 2])), vec![
1122 Arc::new(StringArray::from(vec!["a1", "b2", "b3"])),
1123 Arc::new(Int32Array::new_null(2)), ],
1125 )
1126 .unwrap();
1127
1128 let expected = StringArray::from(vec!["a1", "b3"]);
1129 let extracted = union_extract(&union, "str").unwrap();
1130
1131 assert_eq!(extracted.into_data(), expected.into_data());
1132 }
1133
1134 #[test]
1135 fn dense_5_1a_none_match_less_len() {
1136 let union = UnionArray::try_new(
1137 str1_int3(),
1139 ScalarBuffer::from(vec![3, 3, 3, 3, 3]), Some(ScalarBuffer::from(vec![0, 0, 0, 1, 1])), vec![
1142 Arc::new(StringArray::from(vec!["a1", "b2", "c3"])), Arc::new(Int32Array::from(vec![1, 2])),
1144 ],
1145 )
1146 .unwrap();
1147
1148 let expected = StringArray::new_null(5);
1149 let extracted = union_extract(&union, "str").unwrap();
1150
1151 assert_eq!(extracted.into_data(), expected.into_data());
1152 }
1153
1154 #[test]
1155 fn dense_5_1b_cant_contain_null_mask() {
1156 let target_fields = str1();
1157 let target_type = DataType::Union(target_fields.clone(), UnionMode::Sparse);
1158
1159 let union = UnionArray::try_new(
1160 str1_union3(target_type.clone()),
1162 ScalarBuffer::from(vec![1, 1, 1, 1, 1]), Some(ScalarBuffer::from(vec![0, 0, 0, 1, 1])), vec![
1165 Arc::new(StringArray::from(vec!["a1", "b2", "c3"])), Arc::new(
1167 UnionArray::try_new(
1168 target_fields.clone(),
1169 ScalarBuffer::from(vec![1]),
1170 None,
1171 vec![Arc::new(StringArray::from(vec!["a"]))],
1172 )
1173 .unwrap(),
1174 ), ],
1176 )
1177 .unwrap();
1178
1179 let expected = new_null_array(&target_type, 5);
1180 let extracted = union_extract(&union, "union").unwrap();
1181
1182 assert_eq!(extracted.into_data(), expected.into_data());
1183 }
1184
1185 #[test]
1186 fn dense_5_2_none_match_equal_len() {
1187 let union = UnionArray::try_new(
1188 str1_int3(),
1190 ScalarBuffer::from(vec![3, 3, 3, 3, 3]), Some(ScalarBuffer::from(vec![0, 0, 0, 1, 1])), vec![
1193 Arc::new(StringArray::from(vec!["a1", "b2", "c3", "d4", "e5"])), Arc::new(Int32Array::from(vec![1, 2])),
1195 ],
1196 )
1197 .unwrap();
1198
1199 let expected = StringArray::new_null(5);
1200 let extracted = union_extract(&union, "str").unwrap();
1201
1202 assert_eq!(extracted.into_data(), expected.into_data());
1203 }
1204
1205 #[test]
1206 fn dense_5_3_none_match_greater_len() {
1207 let union = UnionArray::try_new(
1208 str1_int3(),
1210 ScalarBuffer::from(vec![3, 3, 3, 3, 3]), Some(ScalarBuffer::from(vec![0, 0, 0, 1, 1])), vec![
1213 Arc::new(StringArray::from(vec!["a1", "b2", "c3", "d4", "e5", "f6"])), Arc::new(Int32Array::from(vec![1, 2])), ],
1216 )
1217 .unwrap();
1218
1219 let expected = StringArray::new_null(5);
1220 let extracted = union_extract(&union, "str").unwrap();
1221
1222 assert_eq!(extracted.into_data(), expected.into_data());
1223 }
1224
1225 #[test]
1226 fn dense_6_some_matches() {
1227 let union = UnionArray::try_new(
1228 str1_int3(),
1230 ScalarBuffer::from(vec![3, 3, 1, 1, 1]), Some(ScalarBuffer::from(vec![0, 1, 0, 1, 2])), vec![
1233 Arc::new(StringArray::from(vec!["a1", "b2", "c3"])), Arc::new(Int32Array::from(vec![1, 2])),
1235 ],
1236 )
1237 .unwrap();
1238
1239 let expected = Int32Array::from(vec![Some(1), Some(2), None, None, None]);
1240 let extracted = union_extract(&union, "int").unwrap();
1241
1242 assert_eq!(extracted.into_data(), expected.into_data());
1243 }
1244
1245 #[test]
1246 fn empty_sparse_union() {
1247 let union = UnionArray::try_new(
1248 UnionFields::empty(),
1249 ScalarBuffer::from(vec![]),
1250 None,
1251 vec![],
1252 )
1253 .unwrap();
1254
1255 assert_eq!(
1256 union_extract(&union, "a").unwrap_err().to_string(),
1257 ArrowError::InvalidArgumentError("field a not found on union".into()).to_string()
1258 );
1259 }
1260
1261 #[test]
1262 fn empty_dense_union() {
1263 let union = UnionArray::try_new(
1264 UnionFields::empty(),
1265 ScalarBuffer::from(vec![]),
1266 Some(ScalarBuffer::from(vec![])),
1267 vec![],
1268 )
1269 .unwrap();
1270
1271 assert_eq!(
1272 union_extract(&union, "a").unwrap_err().to_string(),
1273 ArrowError::InvalidArgumentError("field a not found on union".into()).to_string()
1274 );
1275 }
1276
1277 #[test]
1278 fn extract_by_id_sparse_duplicate_names() {
1279 let fields = UnionFields::try_new(
1281 [0, 1],
1282 [
1283 Field::new("val", DataType::Int32, true),
1284 Field::new("val", DataType::Utf8, true),
1285 ],
1286 )
1287 .unwrap();
1288
1289 let union = UnionArray::try_new(
1290 fields,
1291 vec![0_i8, 1, 0, 1].into(),
1292 None,
1293 vec![
1294 Arc::new(Int32Array::from(vec![Some(42), None, Some(99), None])) as _,
1295 Arc::new(StringArray::from(vec![
1296 None,
1297 Some("hello"),
1298 None,
1299 Some("world"),
1300 ])),
1301 ],
1302 )
1303 .unwrap();
1304
1305 let by_name = union_extract(&union, "val").unwrap();
1307 assert_eq!(
1308 *by_name,
1309 Int32Array::from(vec![Some(42), None, Some(99), None])
1310 );
1311
1312 let by_id = union_extract_by_id(&union, 1).unwrap();
1314 assert_eq!(
1315 *by_id,
1316 StringArray::from(vec![None, Some("hello"), None, Some("world")])
1317 );
1318 }
1319
1320 #[test]
1321 fn extract_by_id_dense_duplicate_names() {
1322 let fields = UnionFields::try_new(
1323 [0, 1],
1324 [
1325 Field::new("val", DataType::Int32, true),
1326 Field::new("val", DataType::Utf8, true),
1327 ],
1328 )
1329 .unwrap();
1330
1331 let union = UnionArray::try_new(
1332 fields,
1333 vec![0_i8, 1, 0].into(),
1334 Some(vec![0_i32, 0, 1].into()),
1335 vec![
1336 Arc::new(Int32Array::from(vec![Some(42), Some(99)])) as _,
1337 Arc::new(StringArray::from(vec![Some("hello")])),
1338 ],
1339 )
1340 .unwrap();
1341
1342 let by_id_0 = union_extract_by_id(&union, 0).unwrap();
1344 assert_eq!(*by_id_0, Int32Array::from(vec![Some(42), None, Some(99)]));
1345
1346 let by_id_1 = union_extract_by_id(&union, 1).unwrap();
1348 assert_eq!(*by_id_1, StringArray::from(vec![None, Some("hello"), None]));
1349 }
1350
1351 #[test]
1352 fn extract_by_id_not_found() {
1353 let fields = UnionFields::try_new(
1354 [0, 1],
1355 [
1356 Field::new("a", DataType::Int32, true),
1357 Field::new("b", DataType::Utf8, true),
1358 ],
1359 )
1360 .unwrap();
1361
1362 let union = UnionArray::try_new(
1363 fields,
1364 vec![0_i8, 1].into(),
1365 None,
1366 vec![
1367 Arc::new(Int32Array::from(vec![Some(1), None])) as _,
1368 Arc::new(StringArray::from(vec![None, Some("x")])),
1369 ],
1370 )
1371 .unwrap();
1372
1373 assert_eq!(
1374 union_extract_by_id(&union, 5).unwrap_err().to_string(),
1375 ArrowError::InvalidArgumentError("type_id 5 not found on union".into()).to_string()
1376 );
1377 }
1378}