1use std::sync::Arc;
7
8use vortex_buffer::BitBuffer;
9use vortex_buffer::Buffer;
10use vortex_error::VortexExpect;
11use vortex_error::VortexResult;
12use vortex_error::vortex_ensure;
13use vortex_error::vortex_panic;
14
15use crate::ArrayRef;
16use crate::ArraySlots;
17use crate::Executable;
18use crate::ExecutionCtx;
19use crate::IntoArray;
20use crate::array::ArrayView;
21use crate::array::child_to_validity;
22use crate::arrays::Bool;
23use crate::arrays::BoolArray;
24use crate::arrays::Decimal;
25use crate::arrays::DecimalArray;
26use crate::arrays::Extension;
27use crate::arrays::ExtensionArray;
28use crate::arrays::FixedSizeList;
29use crate::arrays::FixedSizeListArray;
30use crate::arrays::ListView;
31use crate::arrays::ListViewArray;
32use crate::arrays::Map;
33use crate::arrays::MapArray;
34use crate::arrays::Null;
35use crate::arrays::NullArray;
36use crate::arrays::Primitive;
37use crate::arrays::PrimitiveArray;
38use crate::arrays::Struct;
39use crate::arrays::StructArray;
40use crate::arrays::Union;
41use crate::arrays::UnionArray;
42use crate::arrays::VarBinView;
43use crate::arrays::VarBinViewArray;
44use crate::arrays::Variant;
45use crate::arrays::VariantArray;
46use crate::arrays::bool::BoolDataParts;
47use crate::arrays::decimal::DecimalDataParts;
48use crate::arrays::extension::ExtensionArrayExt;
49use crate::arrays::fixed_size_list::FixedSizeListArrayExt;
50use crate::arrays::listview::ListViewDataParts;
51use crate::arrays::listview::ListViewRebuildMode;
52use crate::arrays::map::MapArrayExt;
53use crate::arrays::map::MapArraySlotsExt;
54use crate::arrays::primitive::PrimitiveDataParts;
55use crate::arrays::struct_::StructDataParts;
56use crate::arrays::union::UnionDataParts;
57use crate::arrays::varbinview::VarBinViewDataParts;
58use crate::arrays::variant::VariantArraySlotsExt;
59use crate::dtype::DType;
60use crate::dtype::NativePType;
61use crate::dtype::Nullability;
62use crate::dtype::PType;
63use crate::match_each_decimal_value_type;
64use crate::match_each_native_ptype;
65use crate::matcher::Matcher;
66use crate::validity::Validity;
67
68#[derive(Debug, Clone)]
132pub enum Canonical {
133 Null(NullArray),
134 Bool(BoolArray),
135 Primitive(PrimitiveArray),
136 Decimal(DecimalArray),
137 VarBinView(VarBinViewArray),
138 List(ListViewArray),
139 Map(MapArray),
140 FixedSizeList(FixedSizeListArray),
141 Struct(StructArray),
142 Union(UnionArray),
143 Extension(ExtensionArray),
145 Variant(VariantArray),
147}
148
149macro_rules! match_each_canonical {
151 ($self:expr, | $ident:ident | $eval:expr) => {{
152 match $self {
153 Canonical::Null($ident) => $eval,
154 Canonical::Bool($ident) => $eval,
155 Canonical::Primitive($ident) => $eval,
156 Canonical::Decimal($ident) => $eval,
157 Canonical::VarBinView($ident) => $eval,
158 Canonical::List($ident) => $eval,
159 Canonical::Map($ident) => $eval,
160 Canonical::FixedSizeList($ident) => $eval,
161 Canonical::Struct($ident) => $eval,
162 Canonical::Union($ident) => $eval,
163 Canonical::Variant($ident) => $eval,
164 Canonical::Extension($ident) => $eval,
165 }
166 }};
167}
168
169impl Canonical {
170 pub fn empty(dtype: &DType) -> Canonical {
172 match dtype {
173 DType::Null => Canonical::Null(NullArray::new(0)),
174 DType::Bool(n) => Canonical::Bool(unsafe {
175 BoolArray::new_unchecked(BitBuffer::empty(), Validity::from(n))
176 }),
177 DType::Primitive(ptype, n) => {
178 match_each_native_ptype!(ptype, |P| {
179 Canonical::Primitive(unsafe {
180 PrimitiveArray::new_unchecked(Buffer::<P>::empty(), Validity::from(n))
181 })
182 })
183 }
184 DType::Decimal(decimal_type, n) => {
185 match_each_decimal_value_type!(
186 DecimalType::smallest_decimal_value_type(decimal_type),
187 |D| {
188 Canonical::Decimal(unsafe {
189 DecimalArray::new_unchecked::<D>(
190 Buffer::empty(),
191 *decimal_type,
192 Validity::from(n),
193 )
194 })
195 }
196 )
197 }
198 DType::Utf8(n) => Canonical::VarBinView(unsafe {
199 VarBinViewArray::new_unchecked(
200 Buffer::empty(),
201 Arc::new([]),
202 dtype.clone(),
203 Validity::from(n),
204 )
205 }),
206 DType::Binary(n) => Canonical::VarBinView(unsafe {
207 VarBinViewArray::new_unchecked(
208 Buffer::empty(),
209 Arc::new([]),
210 dtype.clone(),
211 Validity::from(n),
212 )
213 }),
214 DType::List(dtype, n) => Canonical::List(unsafe {
215 ListViewArray::new_unchecked(
216 Canonical::empty(dtype).into_array(),
217 Canonical::empty(&DType::Primitive(PType::U8, Nullability::NonNullable))
218 .into_array(),
219 Canonical::empty(&DType::Primitive(PType::U8, Nullability::NonNullable))
220 .into_array(),
221 Validity::from(n),
222 )
223 .with_zero_copy_to_list(true)
225 }),
226 DType::Map(map_dtype, nullability) => Canonical::Map(MapArray::new(
227 map_dtype.clone(),
228 Canonical::empty(&DType::List(
229 Arc::new(map_dtype.entries_dtype()),
230 *nullability,
231 ))
232 .into_listview(),
233 )),
234 DType::FixedSizeList(elem_dtype, list_size, null) => Canonical::FixedSizeList(unsafe {
235 FixedSizeListArray::new_unchecked(
236 Canonical::empty(elem_dtype).into_array(),
237 *list_size,
238 Validity::from(null),
239 0,
240 )
241 }),
242 DType::Struct(struct_dtype, n) => Canonical::Struct(unsafe {
243 StructArray::new_unchecked(
244 struct_dtype
245 .fields()
246 .map(|f| Canonical::empty(&f).into_array())
247 .collect::<Vec<_>>(),
248 struct_dtype.clone(),
249 0,
250 Validity::from(n),
251 )
252 }),
253 DType::Union(variants, nullability) => {
254 Canonical::Union(UnionArray::empty(variants.clone(), *nullability))
255 }
256 DType::Variant(_) => {
257 vortex_panic!(InvalidArgument: "Canonical empty is not supported for Variant")
258 }
259 DType::Extension(ext_dtype) => Canonical::Extension(ExtensionArray::new(
260 ext_dtype.clone(),
261 Canonical::empty(ext_dtype.storage_dtype()).into_array(),
262 )),
263 }
264 }
265
266 pub fn len(&self) -> usize {
267 match_each_canonical!(self, |arr| arr.len())
268 }
269
270 pub fn dtype(&self) -> &DType {
271 match_each_canonical!(self, |arr| arr.dtype())
272 }
273
274 pub fn is_empty(&self) -> bool {
275 match_each_canonical!(self, |arr| arr.is_empty())
276 }
277}
278
279impl Canonical {
280 pub fn compact(&self, ctx: &mut ExecutionCtx) -> VortexResult<Canonical> {
288 match self {
289 Canonical::VarBinView(array) => Ok(Canonical::VarBinView(array.compact_buffers(ctx)?)),
290 Canonical::List(array) => Ok(Canonical::List(
291 array.rebuild(ListViewRebuildMode::TrimElements, ctx)?,
292 )),
293 Canonical::Map(array) => Ok(Canonical::Map(MapArray::new(
294 array.map_dtype().clone(),
295 array
296 .entries()
297 .as_::<ListView>()
298 .into_owned()
299 .rebuild(ListViewRebuildMode::TrimElements, ctx)?,
300 ))),
301 _ => Ok(self.clone()),
302 }
303 }
304}
305
306impl Canonical {
308 pub fn as_null(&self) -> &NullArray {
309 if let Canonical::Null(a) = self {
310 a
311 } else {
312 vortex_panic!("Cannot get NullArray from {:?}", &self)
313 }
314 }
315
316 pub fn into_null(self) -> NullArray {
317 if let Canonical::Null(a) = self {
318 a
319 } else {
320 vortex_panic!("Cannot unwrap NullArray from {:?}", &self)
321 }
322 }
323
324 pub fn as_bool(&self) -> &BoolArray {
325 if let Canonical::Bool(a) = self {
326 a
327 } else {
328 vortex_panic!("Cannot get BoolArray from {:?}", &self)
329 }
330 }
331
332 pub fn into_bool(self) -> BoolArray {
333 if let Canonical::Bool(a) = self {
334 a
335 } else {
336 vortex_panic!("Cannot unwrap BoolArray from {:?}", &self)
337 }
338 }
339
340 pub fn as_primitive(&self) -> &PrimitiveArray {
341 if let Canonical::Primitive(a) = self {
342 a
343 } else {
344 vortex_panic!("Cannot get PrimitiveArray from {:?}", &self)
345 }
346 }
347
348 pub fn into_primitive(self) -> PrimitiveArray {
349 if let Canonical::Primitive(a) = self {
350 a
351 } else {
352 vortex_panic!("Cannot unwrap PrimitiveArray from {:?}", &self)
353 }
354 }
355
356 pub fn as_decimal(&self) -> &DecimalArray {
357 if let Canonical::Decimal(a) = self {
358 a
359 } else {
360 vortex_panic!("Cannot get DecimalArray from {:?}", &self)
361 }
362 }
363
364 pub fn into_decimal(self) -> DecimalArray {
365 if let Canonical::Decimal(a) = self {
366 a
367 } else {
368 vortex_panic!("Cannot unwrap DecimalArray from {:?}", &self)
369 }
370 }
371
372 pub fn as_varbinview(&self) -> &VarBinViewArray {
373 if let Canonical::VarBinView(a) = self {
374 a
375 } else {
376 vortex_panic!("Cannot get VarBinViewArray from {:?}", &self)
377 }
378 }
379
380 pub fn into_varbinview(self) -> VarBinViewArray {
381 if let Canonical::VarBinView(a) = self {
382 a
383 } else {
384 vortex_panic!("Cannot unwrap VarBinViewArray from {:?}", &self)
385 }
386 }
387
388 pub fn as_listview(&self) -> &ListViewArray {
389 if let Canonical::List(a) = self {
390 a
391 } else {
392 vortex_panic!("Cannot get ListArray from {:?}", &self)
393 }
394 }
395
396 pub fn into_listview(self) -> ListViewArray {
397 if let Canonical::List(a) = self {
398 a
399 } else {
400 vortex_panic!("Cannot unwrap ListArray from {:?}", &self)
401 }
402 }
403
404 pub fn as_map(&self) -> &MapArray {
405 if let Canonical::Map(a) = self {
406 a
407 } else {
408 vortex_panic!("Cannot get MapArray from {:?}", &self)
409 }
410 }
411
412 pub fn into_map(self) -> MapArray {
413 if let Canonical::Map(a) = self {
414 a
415 } else {
416 vortex_panic!("Cannot unwrap MapArray from {:?}", &self)
417 }
418 }
419
420 pub fn as_fixed_size_list(&self) -> &FixedSizeListArray {
421 if let Canonical::FixedSizeList(a) = self {
422 a
423 } else {
424 vortex_panic!("Cannot get FixedSizeListArray from {:?}", &self)
425 }
426 }
427
428 pub fn into_fixed_size_list(self) -> FixedSizeListArray {
429 if let Canonical::FixedSizeList(a) = self {
430 a
431 } else {
432 vortex_panic!("Cannot unwrap FixedSizeListArray from {:?}", &self)
433 }
434 }
435
436 pub fn as_struct(&self) -> &StructArray {
437 if let Canonical::Struct(a) = self {
438 a
439 } else {
440 vortex_panic!("Cannot get StructArray from {:?}", &self)
441 }
442 }
443
444 pub fn into_struct(self) -> StructArray {
445 if let Canonical::Struct(a) = self {
446 a
447 } else {
448 vortex_panic!("Cannot unwrap StructArray from {:?}", &self)
449 }
450 }
451
452 pub fn as_union(&self) -> &UnionArray {
454 if let Canonical::Union(a) = self {
455 a
456 } else {
457 vortex_panic!("Cannot get UnionArray from {:?}", &self)
458 }
459 }
460
461 pub fn into_union(self) -> UnionArray {
463 if let Canonical::Union(a) = self {
464 a
465 } else {
466 vortex_panic!("Cannot unwrap UnionArray from {:?}", &self)
467 }
468 }
469
470 pub fn as_extension(&self) -> &ExtensionArray {
471 if let Canonical::Extension(a) = self {
472 a
473 } else {
474 vortex_panic!("Cannot get ExtensionArray from {:?}", &self)
475 }
476 }
477
478 pub fn into_extension(self) -> ExtensionArray {
479 if let Canonical::Extension(a) = self {
480 a
481 } else {
482 vortex_panic!("Cannot unwrap ExtensionArray from {:?}", &self)
483 }
484 }
485}
486
487impl IntoArray for Canonical {
488 fn into_array(self) -> ArrayRef {
489 match_each_canonical!(self, |arr| arr.into_array())
490 }
491}
492
493#[deprecated(note = "use `array.execute::<T>(ctx)` instead")]
499pub trait ToCanonical {
500 #[deprecated(note = "use `array.execute::<NullArray>(ctx)` instead")]
502 fn to_null(&self) -> NullArray;
503
504 #[deprecated(note = "use `array.execute::<BoolArray>(ctx)` instead")]
506 fn to_bool(&self) -> BoolArray;
507
508 #[deprecated(note = "use `array.execute::<PrimitiveArray>(ctx)` instead")]
511 fn to_primitive(&self) -> PrimitiveArray;
512
513 #[deprecated(note = "use `array.execute::<DecimalArray>(ctx)` instead")]
516 fn to_decimal(&self) -> DecimalArray;
517
518 #[deprecated(note = "use `array.execute::<StructArray>(ctx)` instead")]
520 fn to_struct(&self) -> StructArray;
521
522 #[deprecated(note = "use `array.execute::<ListViewArray>(ctx)` instead")]
524 fn to_listview(&self) -> ListViewArray;
525
526 #[deprecated(note = "use `array.execute::<MapArray>(ctx)` instead")]
528 fn to_map(&self) -> MapArray;
529
530 #[deprecated(note = "use `array.execute::<FixedSizeListArray>(ctx)` instead")]
533 fn to_fixed_size_list(&self) -> FixedSizeListArray;
534
535 #[deprecated(note = "use `array.execute::<VarBinViewArray>(ctx)` instead")]
538 fn to_varbinview(&self) -> VarBinViewArray;
539
540 #[deprecated(note = "use `array.execute::<ExtensionArray>(ctx)` instead")]
543 fn to_extension(&self) -> ExtensionArray;
544}
545
546#[expect(deprecated)]
548impl ToCanonical for ArrayRef {
549 fn to_null(&self) -> NullArray {
550 #[expect(deprecated)]
551 let result = self.to_canonical().vortex_expect("to_canonical failed");
552 result.into_null()
553 }
554
555 fn to_bool(&self) -> BoolArray {
556 #[expect(deprecated)]
557 let result = self.to_canonical().vortex_expect("to_canonical failed");
558 result.into_bool()
559 }
560
561 fn to_primitive(&self) -> PrimitiveArray {
562 #[expect(deprecated)]
563 let result = self.to_canonical().vortex_expect("to_canonical failed");
564 result.into_primitive()
565 }
566
567 fn to_decimal(&self) -> DecimalArray {
568 #[expect(deprecated)]
569 let result = self.to_canonical().vortex_expect("to_canonical failed");
570 result.into_decimal()
571 }
572
573 fn to_struct(&self) -> StructArray {
574 #[expect(deprecated)]
575 let result = self.to_canonical().vortex_expect("to_canonical failed");
576 result.into_struct()
577 }
578
579 fn to_listview(&self) -> ListViewArray {
580 #[expect(deprecated)]
581 let result = self.to_canonical().vortex_expect("to_canonical failed");
582 result.into_listview()
583 }
584
585 fn to_map(&self) -> MapArray {
586 #[expect(deprecated)]
587 let result = self.to_canonical().vortex_expect("to_canonical failed");
588 result.into_map()
589 }
590
591 fn to_fixed_size_list(&self) -> FixedSizeListArray {
592 #[expect(deprecated)]
593 let result = self.to_canonical().vortex_expect("to_canonical failed");
594 result.into_fixed_size_list()
595 }
596
597 fn to_varbinview(&self) -> VarBinViewArray {
598 #[expect(deprecated)]
599 let result = self.to_canonical().vortex_expect("to_canonical failed");
600 result.into_varbinview()
601 }
602
603 fn to_extension(&self) -> ExtensionArray {
604 #[expect(deprecated)]
605 let result = self.to_canonical().vortex_expect("to_canonical failed");
606 result.into_extension()
607 }
608}
609
610impl From<Canonical> for ArrayRef {
611 fn from(value: Canonical) -> Self {
612 match_each_canonical!(value, |arr| arr.into_array())
613 }
614}
615
616impl Executable for Canonical {
622 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
623 let result = array.execute_until::<AnyCanonical>(ctx)?;
624 Ok(result
625 .as_opt::<AnyCanonical>()
626 .map(Canonical::from)
627 .vortex_expect("execute_until::<AnyCanonical> must return a canonical array"))
628 }
629}
630
631pub struct CanonicalValidity(pub Canonical);
636
637impl Executable for CanonicalValidity {
638 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
639 match array.execute::<Canonical>(ctx)? {
640 n @ Canonical::Null(_) => Ok(CanonicalValidity(n)),
641 Canonical::Bool(b) => {
642 let validity = child_to_validity(b.slots()[0].as_ref(), b.dtype().nullability());
643 let len = b.len();
644 let BoolDataParts { bits, meta } = b.into_data().into_parts(len);
645 Ok(CanonicalValidity(Canonical::Bool(
646 BoolArray::try_new_from_handle(
647 bits,
648 meta.offset(),
649 meta.len(),
650 validity.execute(ctx)?,
651 )?,
652 )))
653 }
654 Canonical::Primitive(p) => {
655 let PrimitiveDataParts {
656 ptype,
657 buffer,
658 validity,
659 } = p.into_data_parts();
660 Ok(CanonicalValidity(Canonical::Primitive(unsafe {
661 PrimitiveArray::new_unchecked_from_handle(buffer, ptype, validity.execute(ctx)?)
662 })))
663 }
664 Canonical::Decimal(d) => {
665 let DecimalDataParts {
666 decimal_dtype,
667 values,
668 values_type,
669 validity,
670 } = d.into_data_parts();
671 Ok(CanonicalValidity(Canonical::Decimal(unsafe {
672 DecimalArray::new_unchecked_handle(
673 values,
674 values_type,
675 decimal_dtype,
676 validity.execute(ctx)?,
677 )
678 })))
679 }
680 Canonical::VarBinView(vbv) => {
681 let VarBinViewDataParts {
682 dtype,
683 buffers,
684 views,
685 validity,
686 } = vbv.into_data_parts();
687 Ok(CanonicalValidity(Canonical::VarBinView(unsafe {
688 VarBinViewArray::new_handle_unchecked(
689 views,
690 buffers,
691 dtype,
692 validity.execute(ctx)?,
693 )
694 })))
695 }
696 Canonical::List(l) => {
697 let zctl = l.is_zero_copy_to_list();
698 let ListViewDataParts {
699 elements,
700 offsets,
701 sizes,
702 validity,
703 ..
704 } = l.into_data_parts();
705 Ok(CanonicalValidity(Canonical::List(unsafe {
706 ListViewArray::new_unchecked(elements, offsets, sizes, validity.execute(ctx)?)
707 .with_zero_copy_to_list(zctl)
708 })))
709 }
710 Canonical::Map(map) => {
711 let map_dtype = map.map_dtype().clone();
712 let entries = map.entries().clone();
713 Ok(CanonicalValidity(Canonical::Map(MapArray::new(
714 map_dtype,
715 entries.execute::<CanonicalValidity>(ctx)?.0.into_listview(),
716 ))))
717 }
718 Canonical::FixedSizeList(fsl) => {
719 let list_size = fsl.list_size();
720 let len = fsl.len();
721 let parts = fsl.into_data_parts();
722 let elements = parts.elements;
723 let validity = parts.validity;
724 Ok(CanonicalValidity(Canonical::FixedSizeList(
725 FixedSizeListArray::new(elements, list_size, validity.execute(ctx)?, len),
726 )))
727 }
728 Canonical::Struct(st) => {
729 let len = st.len();
730 let StructDataParts {
731 struct_fields,
732 fields,
733 validity,
734 } = st.into_data_parts();
735 Ok(CanonicalValidity(Canonical::Struct(unsafe {
736 StructArray::new_unchecked(fields, struct_fields, len, validity.execute(ctx)?)
737 })))
738 }
739 Canonical::Union(union) => {
740 let UnionDataParts {
741 variants,
742 type_ids,
743 children,
744 } = union.into_data_parts();
745 let type_ids = type_ids.execute::<CanonicalValidity>(ctx)?.0.into_array();
746
747 Ok(CanonicalValidity(Canonical::Union(unsafe {
748 UnionArray::new_unchecked(type_ids, variants, children.iter().cloned())
749 })))
750 }
751 Canonical::Extension(ext) => Ok(CanonicalValidity(Canonical::Extension(
752 ExtensionArray::new(
753 ext.ext_dtype().clone(),
754 ext.storage_array()
755 .clone()
756 .execute::<CanonicalValidity>(ctx)?
757 .0
758 .into_array(),
759 ),
760 ))),
761 Canonical::Variant(variant) => {
762 let core_storage = recursively_canonicalize_slots(variant.core_storage(), ctx)?;
763 let shredded = variant
764 .shredded()
765 .map(|shredded| {
766 if shredded.is::<Variant>() {
767 recursively_canonicalize_slots(shredded, ctx)
768 } else {
769 shredded
770 .clone()
771 .execute::<CanonicalValidity>(ctx)
772 .map(|canonical| canonical.0.into_array())
773 }
774 })
775 .transpose()?;
776 Ok(CanonicalValidity(Canonical::Variant(
777 VariantArray::try_new(core_storage, shredded)?,
778 )))
779 }
780 }
781 }
782}
783
784pub struct RecursiveCanonical(pub Canonical);
789
790fn recursively_canonicalize_slots(
793 array: &ArrayRef,
794 ctx: &mut ExecutionCtx,
795) -> VortexResult<ArrayRef> {
796 let slots = array
797 .slots()
798 .iter()
799 .map(|slot| {
800 slot.as_ref()
801 .map(|child| {
802 child
803 .clone()
804 .execute::<RecursiveCanonical>(ctx)
805 .map(|canonical| canonical.0.into_array())
806 })
807 .transpose()
808 })
809 .collect::<VortexResult<ArraySlots>>()?;
810 unsafe { array.clone().with_slots(slots) }
813}
814impl Executable for RecursiveCanonical {
815 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
816 match array.execute::<Canonical>(ctx)? {
817 n @ Canonical::Null(_) => Ok(RecursiveCanonical(n)),
818 Canonical::Bool(b) => {
819 let validity = child_to_validity(b.slots()[0].as_ref(), b.dtype().nullability());
820 let len = b.len();
821 let BoolDataParts { bits, meta } = b.into_data().into_parts(len);
822 Ok(RecursiveCanonical(Canonical::Bool(
823 BoolArray::try_new_from_handle(
824 bits,
825 meta.offset(),
826 meta.len(),
827 validity.execute(ctx)?,
828 )?,
829 )))
830 }
831 Canonical::Primitive(p) => {
832 let PrimitiveDataParts {
833 ptype,
834 buffer,
835 validity,
836 } = p.into_data_parts();
837 Ok(RecursiveCanonical(Canonical::Primitive(unsafe {
838 PrimitiveArray::new_unchecked_from_handle(buffer, ptype, validity.execute(ctx)?)
839 })))
840 }
841 Canonical::Decimal(d) => {
842 let DecimalDataParts {
843 decimal_dtype,
844 values,
845 values_type,
846 validity,
847 } = d.into_data_parts();
848 Ok(RecursiveCanonical(Canonical::Decimal(unsafe {
849 DecimalArray::new_unchecked_handle(
850 values,
851 values_type,
852 decimal_dtype,
853 validity.execute(ctx)?,
854 )
855 })))
856 }
857 Canonical::VarBinView(vbv) => {
858 let VarBinViewDataParts {
859 dtype,
860 buffers,
861 views,
862 validity,
863 } = vbv.into_data_parts();
864 Ok(RecursiveCanonical(Canonical::VarBinView(unsafe {
865 VarBinViewArray::new_handle_unchecked(
866 views,
867 buffers,
868 dtype,
869 validity.execute(ctx)?,
870 )
871 })))
872 }
873 Canonical::List(l) => {
874 let zctl = l.is_zero_copy_to_list();
875 let ListViewDataParts {
876 elements,
877 offsets,
878 sizes,
879 validity,
880 ..
881 } = l.into_data_parts();
882 Ok(RecursiveCanonical(Canonical::List(unsafe {
883 ListViewArray::new_unchecked(
884 elements.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
885 offsets.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
886 sizes.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
887 validity.execute(ctx)?,
888 )
889 .with_zero_copy_to_list(zctl)
890 })))
891 }
892 Canonical::Map(map) => {
893 let map_dtype = map.map_dtype().clone();
894 let entries = map.entries().clone();
895 Ok(RecursiveCanonical(Canonical::Map(MapArray::new(
896 map_dtype,
897 entries
898 .execute::<RecursiveCanonical>(ctx)?
899 .0
900 .into_listview(),
901 ))))
902 }
903 Canonical::FixedSizeList(fsl) => {
904 let list_size = fsl.list_size();
905 let len = fsl.len();
906 let parts = fsl.into_data_parts();
907 let elements = parts.elements;
908 let validity = parts.validity;
909 Ok(RecursiveCanonical(Canonical::FixedSizeList(
910 FixedSizeListArray::new(
911 elements.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
912 list_size,
913 validity.execute(ctx)?,
914 len,
915 ),
916 )))
917 }
918 Canonical::Struct(st) => {
919 let len = st.len();
920 let StructDataParts {
921 struct_fields,
922 fields,
923 validity,
924 } = st.into_data_parts();
925 let executed_fields = fields
926 .into_iter()
927 .map(|f| Ok(f.execute::<RecursiveCanonical>(ctx)?.0.into_array()))
928 .collect::<VortexResult<Vec<_>>>()?;
929
930 Ok(RecursiveCanonical(Canonical::Struct(unsafe {
931 StructArray::new_unchecked(
932 executed_fields,
933 struct_fields,
934 len,
935 validity.execute(ctx)?,
936 )
937 })))
938 }
939 Canonical::Union(union) => {
940 let UnionDataParts {
941 variants,
942 type_ids,
943 children,
944 } = union.into_data_parts();
945 let type_ids = type_ids.execute::<RecursiveCanonical>(ctx)?.0.into_array();
946 let children = children
947 .iter()
948 .cloned()
949 .map(|child| {
950 child
951 .execute::<RecursiveCanonical>(ctx)
952 .map(|canonical| canonical.0.into_array())
953 })
954 .collect::<VortexResult<Vec<_>>>()?;
955
956 Ok(RecursiveCanonical(Canonical::Union(unsafe {
957 UnionArray::new_unchecked(type_ids, variants, children)
958 })))
959 }
960 Canonical::Extension(ext) => Ok(RecursiveCanonical(Canonical::Extension(
961 ExtensionArray::new(
962 ext.ext_dtype().clone(),
963 ext.storage_array()
964 .clone()
965 .execute::<RecursiveCanonical>(ctx)?
966 .0
967 .into_array(),
968 ),
969 ))),
970 Canonical::Variant(variant) => {
971 let core_storage = recursively_canonicalize_slots(variant.core_storage(), ctx)?;
972 let shredded = variant
973 .shredded()
974 .map(|shredded| {
975 if shredded.is::<Variant>() {
976 recursively_canonicalize_slots(shredded, ctx)
977 } else {
978 shredded
979 .clone()
980 .execute::<RecursiveCanonical>(ctx)
981 .map(|canonical| canonical.0.into_array())
982 }
983 })
984 .transpose()?;
985 Ok(RecursiveCanonical(Canonical::Variant(
986 VariantArray::try_new(core_storage, shredded)?,
987 )))
988 }
989 }
990 }
991}
992
993impl<T: NativePType> Executable for Buffer<T> {
999 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1000 let array = PrimitiveArray::execute(array, ctx)?;
1001 vortex_ensure!(
1002 matches!(
1003 array.validity()?,
1004 Validity::NonNullable | Validity::AllValid
1005 ),
1006 "Cannot execute to native buffer: array is not all-valid."
1007 );
1008 Ok(array.into_buffer())
1009 }
1010}
1011
1012impl Executable for PrimitiveArray {
1016 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1017 match array.try_downcast::<Primitive>() {
1018 Ok(primitive) => Ok(primitive),
1019 Err(array) => Ok(Canonical::execute(array, ctx)?.into_primitive()),
1020 }
1021 }
1022}
1023
1024impl Executable for BoolArray {
1028 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1029 match array.try_downcast::<Bool>() {
1030 Ok(bool_array) => Ok(bool_array),
1031 Err(array) => Ok(Canonical::execute(array, ctx)?.into_bool()),
1032 }
1033 }
1034}
1035
1036impl Executable for BitBuffer {
1040 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1041 let bool = BoolArray::execute(array, ctx)?;
1042 assert!(
1043 !bool.dtype().is_nullable(),
1044 "bit buffer execute only works with non-nullable bool arrays"
1045 );
1046 Ok(bool.into_bit_buffer())
1047 }
1048}
1049
1050impl Executable for NullArray {
1054 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1055 match array.try_downcast::<Null>() {
1056 Ok(null_array) => Ok(null_array),
1057 Err(array) => Ok(Canonical::execute(array, ctx)?.into_null()),
1058 }
1059 }
1060}
1061
1062impl Executable for VarBinViewArray {
1066 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1067 match array.try_downcast::<VarBinView>() {
1068 Ok(varbinview) => Ok(varbinview),
1069 Err(array) => Ok(Canonical::execute(array, ctx)?.into_varbinview()),
1070 }
1071 }
1072}
1073
1074impl Executable for ExtensionArray {
1078 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1079 match array.try_downcast::<Extension>() {
1080 Ok(ext_array) => Ok(ext_array),
1081 Err(array) => Ok(Canonical::execute(array, ctx)?.into_extension()),
1082 }
1083 }
1084}
1085
1086impl Executable for DecimalArray {
1090 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1091 match array.try_downcast::<Decimal>() {
1092 Ok(decimal) => Ok(decimal),
1093 Err(array) => Ok(Canonical::execute(array, ctx)?.into_decimal()),
1094 }
1095 }
1096}
1097
1098impl Executable for ListViewArray {
1102 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1103 match array.try_downcast::<ListView>() {
1104 Ok(list) => Ok(list),
1105 Err(array) => Ok(Canonical::execute(array, ctx)?.into_listview()),
1106 }
1107 }
1108}
1109
1110impl Executable for MapArray {
1114 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1115 match array.try_downcast::<Map>() {
1116 Ok(map) => Ok(map),
1117 Err(array) => Ok(Canonical::execute(array, ctx)?.into_map()),
1118 }
1119 }
1120}
1121
1122impl Executable for FixedSizeListArray {
1126 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1127 match array.try_downcast::<FixedSizeList>() {
1128 Ok(fsl) => Ok(fsl),
1129 Err(array) => Ok(Canonical::execute(array, ctx)?.into_fixed_size_list()),
1130 }
1131 }
1132}
1133
1134impl Executable for StructArray {
1138 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1139 match array.try_downcast::<Struct>() {
1140 Ok(struct_array) => Ok(struct_array),
1141 Err(array) => Ok(Canonical::execute(array, ctx)?.into_struct()),
1142 }
1143 }
1144}
1145
1146impl Executable for UnionArray {
1150 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1151 match array.try_downcast::<Union>() {
1152 Ok(union_array) => Ok(union_array),
1153 Err(array) => Ok(Canonical::execute(array, ctx)?.into_union()),
1154 }
1155 }
1156}
1157
1158impl Executable for VariantArray {
1162 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1163 match array.try_downcast::<Variant>() {
1164 Ok(variant_array) => Ok(variant_array),
1165 Err(array) => match Canonical::execute(array, ctx)? {
1166 Canonical::Variant(variant_array) => Ok(variant_array),
1167 canonical => vortex_panic!("Cannot unwrap VariantArray from {:?}", canonical),
1168 },
1169 }
1170 }
1171}
1172
1173#[derive(Debug, Clone, Copy)]
1178pub enum CanonicalView<'a> {
1179 Null(ArrayView<'a, Null>),
1180 Bool(ArrayView<'a, Bool>),
1181 Primitive(ArrayView<'a, Primitive>),
1182 Decimal(ArrayView<'a, Decimal>),
1183 VarBinView(ArrayView<'a, VarBinView>),
1184 List(ArrayView<'a, ListView>),
1185 Map(ArrayView<'a, Map>),
1186 FixedSizeList(ArrayView<'a, FixedSizeList>),
1187 Struct(ArrayView<'a, Struct>),
1188 Union(ArrayView<'a, Union>),
1189 Extension(ArrayView<'a, Extension>),
1190 Variant(ArrayView<'a, Variant>),
1191}
1192
1193impl From<CanonicalView<'_>> for Canonical {
1194 fn from(value: CanonicalView<'_>) -> Self {
1195 match value {
1196 CanonicalView::Null(a) => Canonical::Null(a.into_owned()),
1197 CanonicalView::Bool(a) => Canonical::Bool(a.into_owned()),
1198 CanonicalView::Primitive(a) => Canonical::Primitive(a.into_owned()),
1199 CanonicalView::Decimal(a) => Canonical::Decimal(a.into_owned()),
1200 CanonicalView::VarBinView(a) => Canonical::VarBinView(a.into_owned()),
1201 CanonicalView::List(a) => Canonical::List(a.into_owned()),
1202 CanonicalView::Map(a) => Canonical::Map(a.into_owned()),
1203 CanonicalView::FixedSizeList(a) => Canonical::FixedSizeList(a.into_owned()),
1204 CanonicalView::Struct(a) => Canonical::Struct(a.into_owned()),
1205 CanonicalView::Union(a) => Canonical::Union(a.into_owned()),
1206 CanonicalView::Extension(a) => Canonical::Extension(a.into_owned()),
1207 CanonicalView::Variant(a) => Canonical::Variant(a.into_owned()),
1208 }
1209 }
1210}
1211
1212impl CanonicalView<'_> {
1213 pub fn to_array_ref(&self) -> ArrayRef {
1215 match self {
1216 CanonicalView::Null(a) => a.array().clone(),
1217 CanonicalView::Bool(a) => a.array().clone(),
1218 CanonicalView::Primitive(a) => a.array().clone(),
1219 CanonicalView::Decimal(a) => a.array().clone(),
1220 CanonicalView::VarBinView(a) => a.array().clone(),
1221 CanonicalView::List(a) => a.array().clone(),
1222 CanonicalView::Map(a) => a.array().clone(),
1223 CanonicalView::FixedSizeList(a) => a.array().clone(),
1224 CanonicalView::Struct(a) => a.array().clone(),
1225 CanonicalView::Union(a) => a.array().clone(),
1226 CanonicalView::Extension(a) => a.array().clone(),
1227 CanonicalView::Variant(a) => a.array().clone(),
1228 }
1229 }
1230}
1231
1232pub struct AnyCanonical;
1234impl Matcher for AnyCanonical {
1235 type Match<'a> = CanonicalView<'a>;
1236
1237 #[inline]
1238 fn matches(array: &ArrayRef) -> bool {
1239 array.is::<Null>()
1240 || array.is::<Bool>()
1241 || array.is::<Primitive>()
1242 || array.is::<Decimal>()
1243 || array.is::<Struct>()
1244 || array.is::<Union>()
1245 || array.is::<ListView>()
1246 || array.is::<Map>()
1247 || array.is::<FixedSizeList>()
1248 || array.is::<VarBinView>()
1249 || array.is::<Variant>()
1250 || array.is::<Extension>()
1251 }
1252
1253 #[inline]
1254 fn try_match(array: &ArrayRef) -> Option<Self::Match<'_>> {
1255 if let Some(a) = array.as_opt::<Null>() {
1256 Some(CanonicalView::Null(a))
1257 } else if let Some(a) = array.as_opt::<Bool>() {
1258 Some(CanonicalView::Bool(a))
1259 } else if let Some(a) = array.as_opt::<Primitive>() {
1260 Some(CanonicalView::Primitive(a))
1261 } else if let Some(a) = array.as_opt::<Decimal>() {
1262 Some(CanonicalView::Decimal(a))
1263 } else if let Some(a) = array.as_opt::<Struct>() {
1264 Some(CanonicalView::Struct(a))
1265 } else if let Some(a) = array.as_opt::<Union>() {
1266 Some(CanonicalView::Union(a))
1267 } else if let Some(a) = array.as_opt::<ListView>() {
1268 Some(CanonicalView::List(a))
1269 } else if let Some(a) = array.as_opt::<Map>() {
1270 Some(CanonicalView::Map(a))
1271 } else if let Some(a) = array.as_opt::<FixedSizeList>() {
1272 Some(CanonicalView::FixedSizeList(a))
1273 } else if let Some(a) = array.as_opt::<VarBinView>() {
1274 Some(CanonicalView::VarBinView(a))
1275 } else if let Some(a) = array.as_opt::<Variant>() {
1276 Some(CanonicalView::Variant(a))
1277 } else {
1278 array.as_opt::<Extension>().map(CanonicalView::Extension)
1279 }
1280 }
1281}
1282
1283#[cfg(test)]
1284mod test {
1285 use std::sync::LazyLock;
1286
1287 use vortex_error::VortexResult;
1288 use vortex_error::vortex_err;
1289 use vortex_session::VortexSession;
1290
1291 use crate::ArrayRef;
1292 use crate::Canonical;
1293 use crate::CanonicalValidity;
1294 use crate::IntoArray;
1295 use crate::VortexSessionExecute;
1296 use crate::arrays::Constant;
1297 use crate::arrays::ConstantArray;
1298 use crate::arrays::Primitive;
1299 use crate::arrays::Struct;
1300 use crate::arrays::Variant;
1301 use crate::arrays::VariantArray;
1302 use crate::arrays::struct_::StructArrayExt;
1303 use crate::arrays::variant::VariantArraySlotsExt;
1304 use crate::canonical::StructArray;
1305 use crate::dtype::Nullability;
1306 use crate::scalar::Scalar;
1307
1308 static SESSION: LazyLock<VortexSession> = LazyLock::new(crate::array_session);
1310
1311 fn variant_core_storage(len: usize) -> ArrayRef {
1312 ConstantArray::new(
1313 Scalar::variant(Scalar::primitive(1i32, Nullability::NonNullable)),
1314 len,
1315 )
1316 .into_array()
1317 }
1318
1319 #[test]
1320 fn canonical_validity_canonicalizes_variant_shredded_physical_slots() -> VortexResult<()> {
1321 let len = 2;
1322 let nested_shredded =
1323 StructArray::try_from_iter([("value", ConstantArray::new(10i32, len).into_array())])?;
1324 let inner_variant = VariantArray::try_new(
1325 variant_core_storage(len),
1326 Some(nested_shredded.into_array()),
1327 )?;
1328 let outer_variant =
1329 VariantArray::try_new(variant_core_storage(len), Some(inner_variant.into_array()))?;
1330
1331 let mut ctx = SESSION.create_execution_ctx();
1332 let Canonical::Variant(canonical) = outer_variant
1333 .into_array()
1334 .execute::<CanonicalValidity>(&mut ctx)?
1335 .0
1336 else {
1337 return Err(vortex_err!("expected canonical variant"));
1338 };
1339
1340 let nested_variant = canonical
1341 .shredded()
1342 .and_then(|shredded| shredded.as_opt::<Variant>())
1343 .ok_or_else(|| vortex_err!("expected nested variant shredded child"))?;
1344 let nested_struct = nested_variant
1345 .shredded()
1346 .and_then(|shredded| shredded.as_opt::<Struct>())
1347 .ok_or_else(|| vortex_err!("expected nested struct shredded child"))?;
1348 let value = nested_struct.unmasked_field_by_name("value")?;
1349
1350 assert!(value.is::<Primitive>());
1351 assert!(!value.is::<Constant>());
1352
1353 Ok(())
1354 }
1355}