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::Bool(array) => Ok(Canonical::Bool(array.trim_bits()?)),
290 Canonical::VarBinView(array) => Ok(Canonical::VarBinView(array.compact_buffers(ctx)?)),
291 Canonical::List(array) => Ok(Canonical::List(
292 array.rebuild(ListViewRebuildMode::TrimElements, ctx)?,
293 )),
294 Canonical::Map(array) => Ok(Canonical::Map(MapArray::new(
295 array.map_dtype().clone(),
296 array
297 .entries()
298 .as_::<ListView>()
299 .into_owned()
300 .rebuild(ListViewRebuildMode::TrimElements, ctx)?,
301 ))),
302 _ => Ok(self.clone()),
303 }
304 }
305}
306
307impl Canonical {
309 pub fn as_null(&self) -> &NullArray {
310 if let Canonical::Null(a) = self {
311 a
312 } else {
313 vortex_panic!("Cannot get NullArray from {:?}", &self)
314 }
315 }
316
317 pub fn into_null(self) -> NullArray {
318 if let Canonical::Null(a) = self {
319 a
320 } else {
321 vortex_panic!("Cannot unwrap NullArray from {:?}", &self)
322 }
323 }
324
325 pub fn as_bool(&self) -> &BoolArray {
326 if let Canonical::Bool(a) = self {
327 a
328 } else {
329 vortex_panic!("Cannot get BoolArray from {:?}", &self)
330 }
331 }
332
333 pub fn into_bool(self) -> BoolArray {
334 if let Canonical::Bool(a) = self {
335 a
336 } else {
337 vortex_panic!("Cannot unwrap BoolArray from {:?}", &self)
338 }
339 }
340
341 pub fn as_primitive(&self) -> &PrimitiveArray {
342 if let Canonical::Primitive(a) = self {
343 a
344 } else {
345 vortex_panic!("Cannot get PrimitiveArray from {:?}", &self)
346 }
347 }
348
349 pub fn into_primitive(self) -> PrimitiveArray {
350 if let Canonical::Primitive(a) = self {
351 a
352 } else {
353 vortex_panic!("Cannot unwrap PrimitiveArray from {:?}", &self)
354 }
355 }
356
357 pub fn as_decimal(&self) -> &DecimalArray {
358 if let Canonical::Decimal(a) = self {
359 a
360 } else {
361 vortex_panic!("Cannot get DecimalArray from {:?}", &self)
362 }
363 }
364
365 pub fn into_decimal(self) -> DecimalArray {
366 if let Canonical::Decimal(a) = self {
367 a
368 } else {
369 vortex_panic!("Cannot unwrap DecimalArray from {:?}", &self)
370 }
371 }
372
373 pub fn as_varbinview(&self) -> &VarBinViewArray {
374 if let Canonical::VarBinView(a) = self {
375 a
376 } else {
377 vortex_panic!("Cannot get VarBinViewArray from {:?}", &self)
378 }
379 }
380
381 pub fn into_varbinview(self) -> VarBinViewArray {
382 if let Canonical::VarBinView(a) = self {
383 a
384 } else {
385 vortex_panic!("Cannot unwrap VarBinViewArray from {:?}", &self)
386 }
387 }
388
389 pub fn as_listview(&self) -> &ListViewArray {
390 if let Canonical::List(a) = self {
391 a
392 } else {
393 vortex_panic!("Cannot get ListArray from {:?}", &self)
394 }
395 }
396
397 pub fn into_listview(self) -> ListViewArray {
398 if let Canonical::List(a) = self {
399 a
400 } else {
401 vortex_panic!("Cannot unwrap ListArray from {:?}", &self)
402 }
403 }
404
405 pub fn as_map(&self) -> &MapArray {
406 if let Canonical::Map(a) = self {
407 a
408 } else {
409 vortex_panic!("Cannot get MapArray from {:?}", &self)
410 }
411 }
412
413 pub fn into_map(self) -> MapArray {
414 if let Canonical::Map(a) = self {
415 a
416 } else {
417 vortex_panic!("Cannot unwrap MapArray from {:?}", &self)
418 }
419 }
420
421 pub fn as_fixed_size_list(&self) -> &FixedSizeListArray {
422 if let Canonical::FixedSizeList(a) = self {
423 a
424 } else {
425 vortex_panic!("Cannot get FixedSizeListArray from {:?}", &self)
426 }
427 }
428
429 pub fn into_fixed_size_list(self) -> FixedSizeListArray {
430 if let Canonical::FixedSizeList(a) = self {
431 a
432 } else {
433 vortex_panic!("Cannot unwrap FixedSizeListArray from {:?}", &self)
434 }
435 }
436
437 pub fn as_struct(&self) -> &StructArray {
438 if let Canonical::Struct(a) = self {
439 a
440 } else {
441 vortex_panic!("Cannot get StructArray from {:?}", &self)
442 }
443 }
444
445 pub fn into_struct(self) -> StructArray {
446 if let Canonical::Struct(a) = self {
447 a
448 } else {
449 vortex_panic!("Cannot unwrap StructArray from {:?}", &self)
450 }
451 }
452
453 pub fn as_union(&self) -> &UnionArray {
455 if let Canonical::Union(a) = self {
456 a
457 } else {
458 vortex_panic!("Cannot get UnionArray from {:?}", &self)
459 }
460 }
461
462 pub fn into_union(self) -> UnionArray {
464 if let Canonical::Union(a) = self {
465 a
466 } else {
467 vortex_panic!("Cannot unwrap UnionArray from {:?}", &self)
468 }
469 }
470
471 pub fn as_extension(&self) -> &ExtensionArray {
472 if let Canonical::Extension(a) = self {
473 a
474 } else {
475 vortex_panic!("Cannot get ExtensionArray from {:?}", &self)
476 }
477 }
478
479 pub fn into_extension(self) -> ExtensionArray {
480 if let Canonical::Extension(a) = self {
481 a
482 } else {
483 vortex_panic!("Cannot unwrap ExtensionArray from {:?}", &self)
484 }
485 }
486}
487
488impl IntoArray for Canonical {
489 fn into_array(self) -> ArrayRef {
490 match_each_canonical!(self, |arr| arr.into_array())
491 }
492}
493
494#[deprecated(note = "use `array.execute::<T>(ctx)` instead")]
500pub trait ToCanonical {
501 #[deprecated(note = "use `array.execute::<NullArray>(ctx)` instead")]
503 fn to_null(&self) -> NullArray;
504
505 #[deprecated(note = "use `array.execute::<BoolArray>(ctx)` instead")]
507 fn to_bool(&self) -> BoolArray;
508
509 #[deprecated(note = "use `array.execute::<PrimitiveArray>(ctx)` instead")]
512 fn to_primitive(&self) -> PrimitiveArray;
513
514 #[deprecated(note = "use `array.execute::<DecimalArray>(ctx)` instead")]
517 fn to_decimal(&self) -> DecimalArray;
518
519 #[deprecated(note = "use `array.execute::<StructArray>(ctx)` instead")]
521 fn to_struct(&self) -> StructArray;
522
523 #[deprecated(note = "use `array.execute::<ListViewArray>(ctx)` instead")]
525 fn to_listview(&self) -> ListViewArray;
526
527 #[deprecated(note = "use `array.execute::<MapArray>(ctx)` instead")]
529 fn to_map(&self) -> MapArray;
530
531 #[deprecated(note = "use `array.execute::<FixedSizeListArray>(ctx)` instead")]
534 fn to_fixed_size_list(&self) -> FixedSizeListArray;
535
536 #[deprecated(note = "use `array.execute::<VarBinViewArray>(ctx)` instead")]
539 fn to_varbinview(&self) -> VarBinViewArray;
540
541 #[deprecated(note = "use `array.execute::<ExtensionArray>(ctx)` instead")]
544 fn to_extension(&self) -> ExtensionArray;
545}
546
547#[expect(deprecated)]
549impl ToCanonical for ArrayRef {
550 fn to_null(&self) -> NullArray {
551 #[expect(deprecated)]
552 let result = self.to_canonical().vortex_expect("to_canonical failed");
553 result.into_null()
554 }
555
556 fn to_bool(&self) -> BoolArray {
557 #[expect(deprecated)]
558 let result = self.to_canonical().vortex_expect("to_canonical failed");
559 result.into_bool()
560 }
561
562 fn to_primitive(&self) -> PrimitiveArray {
563 #[expect(deprecated)]
564 let result = self.to_canonical().vortex_expect("to_canonical failed");
565 result.into_primitive()
566 }
567
568 fn to_decimal(&self) -> DecimalArray {
569 #[expect(deprecated)]
570 let result = self.to_canonical().vortex_expect("to_canonical failed");
571 result.into_decimal()
572 }
573
574 fn to_struct(&self) -> StructArray {
575 #[expect(deprecated)]
576 let result = self.to_canonical().vortex_expect("to_canonical failed");
577 result.into_struct()
578 }
579
580 fn to_listview(&self) -> ListViewArray {
581 #[expect(deprecated)]
582 let result = self.to_canonical().vortex_expect("to_canonical failed");
583 result.into_listview()
584 }
585
586 fn to_map(&self) -> MapArray {
587 #[expect(deprecated)]
588 let result = self.to_canonical().vortex_expect("to_canonical failed");
589 result.into_map()
590 }
591
592 fn to_fixed_size_list(&self) -> FixedSizeListArray {
593 #[expect(deprecated)]
594 let result = self.to_canonical().vortex_expect("to_canonical failed");
595 result.into_fixed_size_list()
596 }
597
598 fn to_varbinview(&self) -> VarBinViewArray {
599 #[expect(deprecated)]
600 let result = self.to_canonical().vortex_expect("to_canonical failed");
601 result.into_varbinview()
602 }
603
604 fn to_extension(&self) -> ExtensionArray {
605 #[expect(deprecated)]
606 let result = self.to_canonical().vortex_expect("to_canonical failed");
607 result.into_extension()
608 }
609}
610
611impl From<Canonical> for ArrayRef {
612 fn from(value: Canonical) -> Self {
613 match_each_canonical!(value, |arr| arr.into_array())
614 }
615}
616
617impl Executable for Canonical {
623 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
624 let result = array.execute_until::<AnyCanonical>(ctx)?;
625 Ok(result
626 .as_opt::<AnyCanonical>()
627 .map(Canonical::from)
628 .vortex_expect("execute_until::<AnyCanonical> must return a canonical array"))
629 }
630}
631
632pub struct CanonicalValidity(pub Canonical);
637
638impl Executable for CanonicalValidity {
639 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
640 match array.execute::<Canonical>(ctx)? {
641 n @ Canonical::Null(_) => Ok(CanonicalValidity(n)),
642 Canonical::Bool(b) => {
643 let validity = child_to_validity(b.slots()[0].as_ref(), b.dtype().nullability());
644 let len = b.len();
645 let BoolDataParts { bits, meta } = b.into_data().into_parts(len);
646 Ok(CanonicalValidity(Canonical::Bool(
647 BoolArray::try_new_from_handle(
648 bits,
649 meta.offset(),
650 meta.len(),
651 validity.execute(ctx)?,
652 )?,
653 )))
654 }
655 Canonical::Primitive(p) => {
656 let PrimitiveDataParts {
657 ptype,
658 buffer,
659 validity,
660 } = p.into_data_parts();
661 Ok(CanonicalValidity(Canonical::Primitive(unsafe {
662 PrimitiveArray::new_unchecked_from_handle(buffer, ptype, validity.execute(ctx)?)
663 })))
664 }
665 Canonical::Decimal(d) => {
666 let DecimalDataParts {
667 decimal_dtype,
668 values,
669 values_type,
670 validity,
671 } = d.into_data_parts();
672 Ok(CanonicalValidity(Canonical::Decimal(unsafe {
673 DecimalArray::new_unchecked_handle(
674 values,
675 values_type,
676 decimal_dtype,
677 validity.execute(ctx)?,
678 )
679 })))
680 }
681 Canonical::VarBinView(vbv) => {
682 let VarBinViewDataParts {
683 dtype,
684 buffers,
685 views,
686 validity,
687 } = vbv.into_data_parts();
688 Ok(CanonicalValidity(Canonical::VarBinView(unsafe {
689 VarBinViewArray::new_handle_unchecked(
690 views,
691 buffers,
692 dtype,
693 validity.execute(ctx)?,
694 )
695 })))
696 }
697 Canonical::List(l) => {
698 let zctl = l.is_zero_copy_to_list();
699 let ListViewDataParts {
700 elements,
701 offsets,
702 sizes,
703 validity,
704 ..
705 } = l.into_data_parts();
706 Ok(CanonicalValidity(Canonical::List(unsafe {
707 ListViewArray::new_unchecked(elements, offsets, sizes, validity.execute(ctx)?)
708 .with_zero_copy_to_list(zctl)
709 })))
710 }
711 Canonical::Map(map) => {
712 let map_dtype = map.map_dtype().clone();
713 let entries = map.entries().clone();
714 Ok(CanonicalValidity(Canonical::Map(MapArray::new(
715 map_dtype,
716 entries.execute::<CanonicalValidity>(ctx)?.0.into_listview(),
717 ))))
718 }
719 Canonical::FixedSizeList(fsl) => {
720 let list_size = fsl.list_size();
721 let len = fsl.len();
722 let parts = fsl.into_data_parts();
723 let elements = parts.elements;
724 let validity = parts.validity;
725 Ok(CanonicalValidity(Canonical::FixedSizeList(
726 FixedSizeListArray::new(elements, list_size, validity.execute(ctx)?, len),
727 )))
728 }
729 Canonical::Struct(st) => {
730 let len = st.len();
731 let StructDataParts {
732 struct_fields,
733 fields,
734 validity,
735 } = st.into_data_parts();
736 Ok(CanonicalValidity(Canonical::Struct(unsafe {
737 StructArray::new_unchecked(fields, struct_fields, len, validity.execute(ctx)?)
738 })))
739 }
740 Canonical::Union(union) => {
741 let UnionDataParts {
742 variants,
743 type_ids,
744 children,
745 } = union.into_data_parts();
746 let type_ids = type_ids.execute::<CanonicalValidity>(ctx)?.0.into_array();
747
748 Ok(CanonicalValidity(Canonical::Union(unsafe {
749 UnionArray::new_unchecked(type_ids, variants, children.iter().cloned())
750 })))
751 }
752 Canonical::Extension(ext) => Ok(CanonicalValidity(Canonical::Extension(
753 ExtensionArray::new(
754 ext.ext_dtype().clone(),
755 ext.storage_array()
756 .clone()
757 .execute::<CanonicalValidity>(ctx)?
758 .0
759 .into_array(),
760 ),
761 ))),
762 Canonical::Variant(variant) => {
763 let core_storage = recursively_canonicalize_slots(variant.core_storage(), ctx)?;
764 let shredded = variant
765 .shredded()
766 .map(|shredded| {
767 if shredded.is::<Variant>() {
768 recursively_canonicalize_slots(shredded, ctx)
769 } else {
770 shredded
771 .clone()
772 .execute::<CanonicalValidity>(ctx)
773 .map(|canonical| canonical.0.into_array())
774 }
775 })
776 .transpose()?;
777 Ok(CanonicalValidity(Canonical::Variant(
778 VariantArray::try_new(core_storage, shredded)?,
779 )))
780 }
781 }
782 }
783}
784
785pub struct RecursiveCanonical(pub Canonical);
790
791fn recursively_canonicalize_slots(
794 array: &ArrayRef,
795 ctx: &mut ExecutionCtx,
796) -> VortexResult<ArrayRef> {
797 let slots = array
798 .slots()
799 .iter()
800 .map(|slot| {
801 slot.as_ref()
802 .map(|child| {
803 child
804 .clone()
805 .execute::<RecursiveCanonical>(ctx)
806 .map(|canonical| canonical.0.into_array())
807 })
808 .transpose()
809 })
810 .collect::<VortexResult<ArraySlots>>()?;
811 unsafe { array.clone().with_slots(slots) }
814}
815impl Executable for RecursiveCanonical {
816 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
817 match array.execute::<Canonical>(ctx)? {
818 n @ Canonical::Null(_) => Ok(RecursiveCanonical(n)),
819 Canonical::Bool(b) => {
820 let validity = child_to_validity(b.slots()[0].as_ref(), b.dtype().nullability());
821 let len = b.len();
822 let BoolDataParts { bits, meta } = b.into_data().into_parts(len);
823 Ok(RecursiveCanonical(Canonical::Bool(
824 BoolArray::try_new_from_handle(
825 bits,
826 meta.offset(),
827 meta.len(),
828 validity.execute(ctx)?,
829 )?,
830 )))
831 }
832 Canonical::Primitive(p) => {
833 let PrimitiveDataParts {
834 ptype,
835 buffer,
836 validity,
837 } = p.into_data_parts();
838 Ok(RecursiveCanonical(Canonical::Primitive(unsafe {
839 PrimitiveArray::new_unchecked_from_handle(buffer, ptype, validity.execute(ctx)?)
840 })))
841 }
842 Canonical::Decimal(d) => {
843 let DecimalDataParts {
844 decimal_dtype,
845 values,
846 values_type,
847 validity,
848 } = d.into_data_parts();
849 Ok(RecursiveCanonical(Canonical::Decimal(unsafe {
850 DecimalArray::new_unchecked_handle(
851 values,
852 values_type,
853 decimal_dtype,
854 validity.execute(ctx)?,
855 )
856 })))
857 }
858 Canonical::VarBinView(vbv) => {
859 let VarBinViewDataParts {
860 dtype,
861 buffers,
862 views,
863 validity,
864 } = vbv.into_data_parts();
865 Ok(RecursiveCanonical(Canonical::VarBinView(unsafe {
866 VarBinViewArray::new_handle_unchecked(
867 views,
868 buffers,
869 dtype,
870 validity.execute(ctx)?,
871 )
872 })))
873 }
874 Canonical::List(l) => {
875 let zctl = l.is_zero_copy_to_list();
876 let ListViewDataParts {
877 elements,
878 offsets,
879 sizes,
880 validity,
881 ..
882 } = l.into_data_parts();
883 Ok(RecursiveCanonical(Canonical::List(unsafe {
884 ListViewArray::new_unchecked(
885 elements.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
886 offsets.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
887 sizes.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
888 validity.execute(ctx)?,
889 )
890 .with_zero_copy_to_list(zctl)
891 })))
892 }
893 Canonical::Map(map) => {
894 let map_dtype = map.map_dtype().clone();
895 let entries = map.entries().clone();
896 Ok(RecursiveCanonical(Canonical::Map(MapArray::new(
897 map_dtype,
898 entries
899 .execute::<RecursiveCanonical>(ctx)?
900 .0
901 .into_listview(),
902 ))))
903 }
904 Canonical::FixedSizeList(fsl) => {
905 let list_size = fsl.list_size();
906 let len = fsl.len();
907 let parts = fsl.into_data_parts();
908 let elements = parts.elements;
909 let validity = parts.validity;
910 Ok(RecursiveCanonical(Canonical::FixedSizeList(
911 FixedSizeListArray::new(
912 elements.execute::<RecursiveCanonical>(ctx)?.0.into_array(),
913 list_size,
914 validity.execute(ctx)?,
915 len,
916 ),
917 )))
918 }
919 Canonical::Struct(st) => {
920 let len = st.len();
921 let StructDataParts {
922 struct_fields,
923 fields,
924 validity,
925 } = st.into_data_parts();
926 let executed_fields = fields
927 .into_iter()
928 .map(|f| Ok(f.execute::<RecursiveCanonical>(ctx)?.0.into_array()))
929 .collect::<VortexResult<Vec<_>>>()?;
930
931 Ok(RecursiveCanonical(Canonical::Struct(unsafe {
932 StructArray::new_unchecked(
933 executed_fields,
934 struct_fields,
935 len,
936 validity.execute(ctx)?,
937 )
938 })))
939 }
940 Canonical::Union(union) => {
941 let UnionDataParts {
942 variants,
943 type_ids,
944 children,
945 } = union.into_data_parts();
946 let type_ids = type_ids.execute::<RecursiveCanonical>(ctx)?.0.into_array();
947 let children = children
948 .iter()
949 .cloned()
950 .map(|child| {
951 child
952 .execute::<RecursiveCanonical>(ctx)
953 .map(|canonical| canonical.0.into_array())
954 })
955 .collect::<VortexResult<Vec<_>>>()?;
956
957 Ok(RecursiveCanonical(Canonical::Union(unsafe {
958 UnionArray::new_unchecked(type_ids, variants, children)
959 })))
960 }
961 Canonical::Extension(ext) => Ok(RecursiveCanonical(Canonical::Extension(
962 ExtensionArray::new(
963 ext.ext_dtype().clone(),
964 ext.storage_array()
965 .clone()
966 .execute::<RecursiveCanonical>(ctx)?
967 .0
968 .into_array(),
969 ),
970 ))),
971 Canonical::Variant(variant) => {
972 let core_storage = recursively_canonicalize_slots(variant.core_storage(), ctx)?;
973 let shredded = variant
974 .shredded()
975 .map(|shredded| {
976 if shredded.is::<Variant>() {
977 recursively_canonicalize_slots(shredded, ctx)
978 } else {
979 shredded
980 .clone()
981 .execute::<RecursiveCanonical>(ctx)
982 .map(|canonical| canonical.0.into_array())
983 }
984 })
985 .transpose()?;
986 Ok(RecursiveCanonical(Canonical::Variant(
987 VariantArray::try_new(core_storage, shredded)?,
988 )))
989 }
990 }
991 }
992}
993
994impl<T: NativePType> Executable for Buffer<T> {
1000 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1001 let array = PrimitiveArray::execute(array, ctx)?;
1002 vortex_ensure!(
1003 matches!(
1004 array.validity()?,
1005 Validity::NonNullable | Validity::AllValid
1006 ),
1007 "Cannot execute to native buffer: array is not all-valid."
1008 );
1009 Ok(array.into_buffer())
1010 }
1011}
1012
1013impl Executable for PrimitiveArray {
1017 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1018 match array.try_downcast::<Primitive>() {
1019 Ok(primitive) => Ok(primitive),
1020 Err(array) => Ok(Canonical::execute(array, ctx)?.into_primitive()),
1021 }
1022 }
1023}
1024
1025impl Executable for BoolArray {
1029 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1030 match array.try_downcast::<Bool>() {
1031 Ok(bool_array) => Ok(bool_array),
1032 Err(array) => Ok(Canonical::execute(array, ctx)?.into_bool()),
1033 }
1034 }
1035}
1036
1037impl Executable for BitBuffer {
1041 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1042 let bool = BoolArray::execute(array, ctx)?;
1043 assert!(
1044 !bool.dtype().is_nullable(),
1045 "bit buffer execute only works with non-nullable bool arrays"
1046 );
1047 Ok(bool.into_bit_buffer())
1048 }
1049}
1050
1051impl Executable for NullArray {
1055 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1056 match array.try_downcast::<Null>() {
1057 Ok(null_array) => Ok(null_array),
1058 Err(array) => Ok(Canonical::execute(array, ctx)?.into_null()),
1059 }
1060 }
1061}
1062
1063impl Executable for VarBinViewArray {
1067 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1068 match array.try_downcast::<VarBinView>() {
1069 Ok(varbinview) => Ok(varbinview),
1070 Err(array) => Ok(Canonical::execute(array, ctx)?.into_varbinview()),
1071 }
1072 }
1073}
1074
1075impl Executable for ExtensionArray {
1079 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1080 match array.try_downcast::<Extension>() {
1081 Ok(ext_array) => Ok(ext_array),
1082 Err(array) => Ok(Canonical::execute(array, ctx)?.into_extension()),
1083 }
1084 }
1085}
1086
1087impl Executable for DecimalArray {
1091 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1092 match array.try_downcast::<Decimal>() {
1093 Ok(decimal) => Ok(decimal),
1094 Err(array) => Ok(Canonical::execute(array, ctx)?.into_decimal()),
1095 }
1096 }
1097}
1098
1099impl Executable for ListViewArray {
1103 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1104 match array.try_downcast::<ListView>() {
1105 Ok(list) => Ok(list),
1106 Err(array) => Ok(Canonical::execute(array, ctx)?.into_listview()),
1107 }
1108 }
1109}
1110
1111impl Executable for MapArray {
1115 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1116 match array.try_downcast::<Map>() {
1117 Ok(map) => Ok(map),
1118 Err(array) => Ok(Canonical::execute(array, ctx)?.into_map()),
1119 }
1120 }
1121}
1122
1123impl Executable for FixedSizeListArray {
1127 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1128 match array.try_downcast::<FixedSizeList>() {
1129 Ok(fsl) => Ok(fsl),
1130 Err(array) => Ok(Canonical::execute(array, ctx)?.into_fixed_size_list()),
1131 }
1132 }
1133}
1134
1135impl Executable for StructArray {
1139 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1140 match array.try_downcast::<Struct>() {
1141 Ok(struct_array) => Ok(struct_array),
1142 Err(array) => Ok(Canonical::execute(array, ctx)?.into_struct()),
1143 }
1144 }
1145}
1146
1147impl Executable for UnionArray {
1151 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1152 match array.try_downcast::<Union>() {
1153 Ok(union_array) => Ok(union_array),
1154 Err(array) => Ok(Canonical::execute(array, ctx)?.into_union()),
1155 }
1156 }
1157}
1158
1159impl Executable for VariantArray {
1163 fn execute(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
1164 match array.try_downcast::<Variant>() {
1165 Ok(variant_array) => Ok(variant_array),
1166 Err(array) => match Canonical::execute(array, ctx)? {
1167 Canonical::Variant(variant_array) => Ok(variant_array),
1168 canonical => vortex_panic!("Cannot unwrap VariantArray from {:?}", canonical),
1169 },
1170 }
1171 }
1172}
1173
1174#[derive(Debug, Clone, Copy)]
1179pub enum CanonicalView<'a> {
1180 Null(ArrayView<'a, Null>),
1181 Bool(ArrayView<'a, Bool>),
1182 Primitive(ArrayView<'a, Primitive>),
1183 Decimal(ArrayView<'a, Decimal>),
1184 VarBinView(ArrayView<'a, VarBinView>),
1185 List(ArrayView<'a, ListView>),
1186 Map(ArrayView<'a, Map>),
1187 FixedSizeList(ArrayView<'a, FixedSizeList>),
1188 Struct(ArrayView<'a, Struct>),
1189 Union(ArrayView<'a, Union>),
1190 Extension(ArrayView<'a, Extension>),
1191 Variant(ArrayView<'a, Variant>),
1192}
1193
1194impl From<CanonicalView<'_>> for Canonical {
1195 fn from(value: CanonicalView<'_>) -> Self {
1196 match value {
1197 CanonicalView::Null(a) => Canonical::Null(a.into_owned()),
1198 CanonicalView::Bool(a) => Canonical::Bool(a.into_owned()),
1199 CanonicalView::Primitive(a) => Canonical::Primitive(a.into_owned()),
1200 CanonicalView::Decimal(a) => Canonical::Decimal(a.into_owned()),
1201 CanonicalView::VarBinView(a) => Canonical::VarBinView(a.into_owned()),
1202 CanonicalView::List(a) => Canonical::List(a.into_owned()),
1203 CanonicalView::Map(a) => Canonical::Map(a.into_owned()),
1204 CanonicalView::FixedSizeList(a) => Canonical::FixedSizeList(a.into_owned()),
1205 CanonicalView::Struct(a) => Canonical::Struct(a.into_owned()),
1206 CanonicalView::Union(a) => Canonical::Union(a.into_owned()),
1207 CanonicalView::Extension(a) => Canonical::Extension(a.into_owned()),
1208 CanonicalView::Variant(a) => Canonical::Variant(a.into_owned()),
1209 }
1210 }
1211}
1212
1213impl CanonicalView<'_> {
1214 pub fn to_array_ref(&self) -> ArrayRef {
1216 match self {
1217 CanonicalView::Null(a) => a.array().clone(),
1218 CanonicalView::Bool(a) => a.array().clone(),
1219 CanonicalView::Primitive(a) => a.array().clone(),
1220 CanonicalView::Decimal(a) => a.array().clone(),
1221 CanonicalView::VarBinView(a) => a.array().clone(),
1222 CanonicalView::List(a) => a.array().clone(),
1223 CanonicalView::Map(a) => a.array().clone(),
1224 CanonicalView::FixedSizeList(a) => a.array().clone(),
1225 CanonicalView::Struct(a) => a.array().clone(),
1226 CanonicalView::Union(a) => a.array().clone(),
1227 CanonicalView::Extension(a) => a.array().clone(),
1228 CanonicalView::Variant(a) => a.array().clone(),
1229 }
1230 }
1231}
1232
1233pub struct AnyCanonical;
1235impl Matcher for AnyCanonical {
1236 type Match<'a> = CanonicalView<'a>;
1237
1238 #[inline]
1239 fn matches(array: &ArrayRef) -> bool {
1240 array.is::<Null>()
1241 || array.is::<Bool>()
1242 || array.is::<Primitive>()
1243 || array.is::<Decimal>()
1244 || array.is::<Struct>()
1245 || array.is::<Union>()
1246 || array.is::<ListView>()
1247 || array.is::<Map>()
1248 || array.is::<FixedSizeList>()
1249 || array.is::<VarBinView>()
1250 || array.is::<Variant>()
1251 || array.is::<Extension>()
1252 }
1253
1254 #[inline]
1255 fn try_match(array: &ArrayRef) -> Option<Self::Match<'_>> {
1256 if let Some(a) = array.as_opt::<Null>() {
1257 Some(CanonicalView::Null(a))
1258 } else if let Some(a) = array.as_opt::<Bool>() {
1259 Some(CanonicalView::Bool(a))
1260 } else if let Some(a) = array.as_opt::<Primitive>() {
1261 Some(CanonicalView::Primitive(a))
1262 } else if let Some(a) = array.as_opt::<Decimal>() {
1263 Some(CanonicalView::Decimal(a))
1264 } else if let Some(a) = array.as_opt::<Struct>() {
1265 Some(CanonicalView::Struct(a))
1266 } else if let Some(a) = array.as_opt::<Union>() {
1267 Some(CanonicalView::Union(a))
1268 } else if let Some(a) = array.as_opt::<ListView>() {
1269 Some(CanonicalView::List(a))
1270 } else if let Some(a) = array.as_opt::<Map>() {
1271 Some(CanonicalView::Map(a))
1272 } else if let Some(a) = array.as_opt::<FixedSizeList>() {
1273 Some(CanonicalView::FixedSizeList(a))
1274 } else if let Some(a) = array.as_opt::<VarBinView>() {
1275 Some(CanonicalView::VarBinView(a))
1276 } else if let Some(a) = array.as_opt::<Variant>() {
1277 Some(CanonicalView::Variant(a))
1278 } else {
1279 array.as_opt::<Extension>().map(CanonicalView::Extension)
1280 }
1281 }
1282}
1283
1284#[cfg(test)]
1285mod test {
1286 use std::sync::LazyLock;
1287
1288 use vortex_error::VortexResult;
1289 use vortex_error::vortex_err;
1290 use vortex_session::VortexSession;
1291
1292 use crate::ArrayRef;
1293 use crate::Canonical;
1294 use crate::CanonicalValidity;
1295 use crate::IntoArray;
1296 use crate::VortexSessionExecute;
1297 use crate::arrays::Constant;
1298 use crate::arrays::ConstantArray;
1299 use crate::arrays::Primitive;
1300 use crate::arrays::Struct;
1301 use crate::arrays::Variant;
1302 use crate::arrays::VariantArray;
1303 use crate::arrays::struct_::StructArrayExt;
1304 use crate::arrays::variant::VariantArraySlotsExt;
1305 use crate::canonical::StructArray;
1306 use crate::dtype::Nullability;
1307 use crate::scalar::Scalar;
1308
1309 static SESSION: LazyLock<VortexSession> = LazyLock::new(crate::array_session);
1311
1312 fn variant_core_storage(len: usize) -> ArrayRef {
1313 ConstantArray::new(
1314 Scalar::variant(Scalar::primitive(1i32, Nullability::NonNullable)),
1315 len,
1316 )
1317 .into_array()
1318 }
1319
1320 #[test]
1321 fn canonical_validity_canonicalizes_variant_shredded_physical_slots() -> VortexResult<()> {
1322 let len = 2;
1323 let nested_shredded =
1324 StructArray::try_from_iter([("value", ConstantArray::new(10i32, len).into_array())])?;
1325 let inner_variant = VariantArray::try_new(
1326 variant_core_storage(len),
1327 Some(nested_shredded.into_array()),
1328 )?;
1329 let outer_variant =
1330 VariantArray::try_new(variant_core_storage(len), Some(inner_variant.into_array()))?;
1331
1332 let mut ctx = SESSION.create_execution_ctx();
1333 let Canonical::Variant(canonical) = outer_variant
1334 .into_array()
1335 .execute::<CanonicalValidity>(&mut ctx)?
1336 .0
1337 else {
1338 return Err(vortex_err!("expected canonical variant"));
1339 };
1340
1341 let nested_variant = canonical
1342 .shredded()
1343 .and_then(|shredded| shredded.as_opt::<Variant>())
1344 .ok_or_else(|| vortex_err!("expected nested variant shredded child"))?;
1345 let nested_struct = nested_variant
1346 .shredded()
1347 .and_then(|shredded| shredded.as_opt::<Struct>())
1348 .ok_or_else(|| vortex_err!("expected nested struct shredded child"))?;
1349 let value = nested_struct.unmasked_field_by_name("value")?;
1350
1351 assert!(value.is::<Primitive>());
1352 assert!(!value.is::<Constant>());
1353
1354 Ok(())
1355 }
1356}