vortex_array/arrays/null/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::hash::Hash;
5use std::ops::Range;
6
7use vortex_buffer::BufferHandle;
8use vortex_dtype::DType;
9use vortex_error::VortexResult;
10use vortex_mask::Mask;
11use vortex_scalar::Scalar;
12use vortex_vector::Vector;
13use vortex_vector::null::NullVector;
14
15use crate::ArrayBufferVisitor;
16use crate::ArrayChildVisitor;
17use crate::ArrayRef;
18use crate::Canonical;
19use crate::EmptyMetadata;
20use crate::IntoArray;
21use crate::Precision;
22use crate::execution::ExecutionCtx;
23use crate::serde::ArrayChildren;
24use crate::stats::ArrayStats;
25use crate::stats::StatsSetRef;
26use crate::vtable;
27use crate::vtable::ArrayId;
28use crate::vtable::ArrayVTable;
29use crate::vtable::ArrayVTableExt;
30use crate::vtable::BaseArrayVTable;
31use crate::vtable::CanonicalVTable;
32use crate::vtable::NotSupported;
33use crate::vtable::OperationsVTable;
34use crate::vtable::VTable;
35use crate::vtable::ValidityVTable;
36use crate::vtable::VisitorVTable;
37
38mod compute;
39
40vtable!(Null);
41
42impl VTable for NullVTable {
43    type Array = NullArray;
44
45    type Metadata = EmptyMetadata;
46
47    type ArrayVTable = Self;
48    type CanonicalVTable = Self;
49    type OperationsVTable = Self;
50    type ValidityVTable = Self;
51    type VisitorVTable = Self;
52    type ComputeVTable = NotSupported;
53    type EncodeVTable = NotSupported;
54
55    fn id(&self) -> ArrayId {
56        ArrayId::new_ref("vortex.null")
57    }
58
59    fn encoding(_array: &Self::Array) -> ArrayVTable {
60        NullVTable.as_vtable()
61    }
62
63    fn metadata(_array: &NullArray) -> VortexResult<Self::Metadata> {
64        Ok(EmptyMetadata)
65    }
66
67    fn serialize(_metadata: Self::Metadata) -> VortexResult<Option<Vec<u8>>> {
68        Ok(Some(vec![]))
69    }
70
71    fn deserialize(_buffer: &[u8]) -> VortexResult<Self::Metadata> {
72        Ok(EmptyMetadata)
73    }
74
75    fn build(
76        &self,
77        _dtype: &DType,
78        len: usize,
79        _metadata: &Self::Metadata,
80        _buffers: &[BufferHandle],
81        _children: &dyn ArrayChildren,
82    ) -> VortexResult<NullArray> {
83        Ok(NullArray::new(len))
84    }
85
86    fn batch_execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult<Vector> {
87        Ok(NullVector::new(array.len()).into())
88    }
89}
90
91/// A array where all values are null.
92///
93/// This mirrors the Apache Arrow Null array encoding and provides an efficient representation
94/// for arrays containing only null values. No actual data is stored, only the length.
95///
96/// All operations on null arrays return null values or indicate invalid data.
97///
98/// # Examples
99///
100/// ```
101/// use vortex_array::arrays::NullArray;
102/// use vortex_array::IntoArray;
103///
104/// // Create a null array with 5 elements
105/// let array = NullArray::new(5);
106///
107/// // Slice the array - still contains nulls
108/// let sliced = array.slice(1..3);
109/// assert_eq!(sliced.len(), 2);
110///
111/// // All elements are null
112/// let scalar = array.scalar_at(0);
113/// assert!(scalar.is_null());
114/// ```
115#[derive(Clone, Debug)]
116pub struct NullArray {
117    len: usize,
118    stats_set: ArrayStats,
119}
120
121#[derive(Debug)]
122pub struct NullVTable;
123
124impl NullArray {
125    pub fn new(len: usize) -> Self {
126        Self {
127            len,
128            stats_set: Default::default(),
129        }
130    }
131}
132
133impl BaseArrayVTable<NullVTable> for NullVTable {
134    fn len(array: &NullArray) -> usize {
135        array.len
136    }
137
138    fn dtype(_array: &NullArray) -> &DType {
139        &DType::Null
140    }
141
142    fn stats(array: &NullArray) -> StatsSetRef<'_> {
143        array.stats_set.to_ref(array.as_ref())
144    }
145
146    fn array_hash<H: std::hash::Hasher>(array: &NullArray, state: &mut H, _precision: Precision) {
147        array.len.hash(state);
148    }
149
150    fn array_eq(array: &NullArray, other: &NullArray, _precision: Precision) -> bool {
151        array.len == other.len
152    }
153}
154
155impl VisitorVTable<NullVTable> for NullVTable {
156    fn visit_buffers(_array: &NullArray, _visitor: &mut dyn ArrayBufferVisitor) {}
157
158    fn visit_children(_array: &NullArray, _visitor: &mut dyn ArrayChildVisitor) {}
159}
160
161impl CanonicalVTable<NullVTable> for NullVTable {
162    fn canonicalize(array: &NullArray) -> Canonical {
163        Canonical::Null(array.clone())
164    }
165}
166
167impl OperationsVTable<NullVTable> for NullVTable {
168    fn slice(_array: &NullArray, range: Range<usize>) -> ArrayRef {
169        NullArray::new(range.len()).into_array()
170    }
171
172    fn scalar_at(_array: &NullArray, _index: usize) -> Scalar {
173        Scalar::null(DType::Null)
174    }
175}
176
177impl ValidityVTable<NullVTable> for NullVTable {
178    fn is_valid(_array: &NullArray, _index: usize) -> bool {
179        false
180    }
181
182    fn all_valid(array: &NullArray) -> bool {
183        array.is_empty()
184    }
185
186    fn all_invalid(array: &NullArray) -> bool {
187        !array.is_empty()
188    }
189
190    fn validity_mask(array: &NullArray) -> Mask {
191        Mask::AllFalse(array.len)
192    }
193}