Skip to main content

vortex_array/arrays/null/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_error::VortexResult;
5use vortex_error::vortex_ensure;
6use vortex_error::vortex_panic;
7use vortex_session::VortexSession;
8use vortex_session::registry::CachedId;
9
10use crate::ArrayRef;
11use crate::ExecutionCtx;
12use crate::ExecutionResult;
13use crate::array::Array;
14use crate::array::ArrayId;
15use crate::array::ArrayParts;
16use crate::array::ArrayView;
17use crate::array::EmptyArrayData;
18use crate::array::OperationsVTable;
19use crate::array::VTable;
20use crate::array::ValidityVTable;
21use crate::arrays::null::compute::rules::PARENT_RULES;
22use crate::buffer::BufferHandle;
23use crate::dtype::DType;
24use crate::scalar::Scalar;
25use crate::serde::ArrayChildren;
26use crate::validity::Validity;
27
28pub(crate) mod compute;
29
30/// A [`Null`]-encoded Vortex array.
31pub type NullArray = Array<Null>;
32
33impl VTable for Null {
34    type ArrayData = EmptyArrayData;
35
36    type OperationsVTable = Self;
37    type ValidityVTable = Self;
38
39    fn id(&self) -> ArrayId {
40        static ID: CachedId = CachedId::new("vortex.null");
41        *ID
42    }
43
44    fn validate(
45        &self,
46        _data: &EmptyArrayData,
47        dtype: &DType,
48        _len: usize,
49        _slots: &[Option<ArrayRef>],
50    ) -> VortexResult<()> {
51        vortex_ensure!(*dtype == DType::Null, "NullArray dtype must be DType::Null");
52        Ok(())
53    }
54
55    fn nbuffers(_array: ArrayView<'_, Self>) -> usize {
56        0
57    }
58
59    fn buffer(_array: ArrayView<'_, Self>, idx: usize) -> BufferHandle {
60        vortex_panic!("NullArray buffer index {idx} out of bounds")
61    }
62
63    fn buffer_name(_array: ArrayView<'_, Self>, _idx: usize) -> Option<String> {
64        None
65    }
66
67    fn slot_name(_array: ArrayView<'_, Self>, idx: usize) -> String {
68        vortex_panic!("NullArray slot_name index {idx} out of bounds")
69    }
70
71    fn serialize(
72        _array: ArrayView<'_, Self>,
73        _session: &VortexSession,
74    ) -> VortexResult<Option<Vec<u8>>> {
75        Ok(Some(vec![]))
76    }
77
78    fn deserialize(
79        &self,
80        dtype: &DType,
81        len: usize,
82        metadata: &[u8],
83
84        _buffers: &[BufferHandle],
85        _children: &dyn ArrayChildren,
86        _session: &VortexSession,
87    ) -> VortexResult<ArrayParts<Self>> {
88        vortex_ensure!(
89            metadata.is_empty(),
90            "NullArray expects empty metadata, got {} bytes",
91            metadata.len()
92        );
93        Ok(ArrayParts::new(
94            self.clone(),
95            dtype.clone(),
96            len,
97            EmptyArrayData,
98        ))
99    }
100
101    fn reduce_parent(
102        array: ArrayView<'_, Self>,
103        parent: &ArrayRef,
104        child_idx: usize,
105    ) -> VortexResult<Option<ArrayRef>> {
106        PARENT_RULES.evaluate(array, parent, child_idx)
107    }
108
109    fn execute(array: Array<Self>, _ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
110        Ok(ExecutionResult::done(array))
111    }
112}
113
114/// A array where all values are null.
115///
116/// This mirrors the Apache Arrow Null array encoding and provides an efficient representation
117/// for arrays containing only null values. No actual data is stored, only the length.
118///
119/// All operations on null arrays return null values or indicate invalid data.
120///
121/// # Examples
122///
123/// ```
124/// # fn main() -> vortex_error::VortexResult<()> {
125/// use vortex_array::arrays::NullArray;
126/// use vortex_array::{IntoArray, LEGACY_SESSION, VortexSessionExecute};
127///
128/// // Create a null array with 5 elements
129/// let array = NullArray::new(5);
130///
131/// // Slice the array - still contains nulls
132/// let sliced = array.slice(1..3)?;
133/// assert_eq!(sliced.len(), 2);
134///
135/// // All elements are null
136/// let mut ctx = LEGACY_SESSION.create_execution_ctx();
137/// let scalar = array.execute_scalar(0, &mut ctx).unwrap();
138/// assert!(scalar.is_null());
139/// # Ok(())
140/// # }
141/// ```
142#[derive(Clone, Debug)]
143pub struct Null;
144
145impl Array<Null> {
146    pub fn new(len: usize) -> Self {
147        unsafe {
148            Array::from_parts_unchecked(ArrayParts::new(Null, DType::Null, len, EmptyArrayData))
149        }
150    }
151}
152
153impl OperationsVTable<Null> for Null {
154    fn scalar_at(
155        _array: ArrayView<'_, Null>,
156        _index: usize,
157        _ctx: &mut ExecutionCtx,
158    ) -> VortexResult<Scalar> {
159        Ok(Scalar::null(DType::Null))
160    }
161}
162
163impl ValidityVTable<Null> for Null {
164    fn validity(_array: ArrayView<'_, Null>) -> VortexResult<Validity> {
165        Ok(Validity::AllInvalid)
166    }
167}