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