vortex_array/arrays/null/compute/
cast.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_dtype::DType;
5use vortex_error::VortexResult;
6use vortex_error::vortex_bail;
7use vortex_scalar::Scalar;
8use vortex_scalar::ScalarValue;
9
10use crate::ArrayRef;
11use crate::IntoArray;
12use crate::arrays::ConstantArray;
13use crate::arrays::NullArray;
14use crate::arrays::NullVTable;
15use crate::compute::CastKernel;
16use crate::compute::CastKernelAdapter;
17use crate::register_kernel;
18
19impl CastKernel for NullVTable {
20    fn cast(&self, array: &NullArray, dtype: &DType) -> VortexResult<Option<ArrayRef>> {
21        if !dtype.is_nullable() {
22            vortex_bail!("Cannot cast Null to {}", dtype);
23        }
24        if dtype == &DType::Null {
25            return Ok(Some(array.to_array()));
26        }
27
28        let scalar = Scalar::new(dtype.clone(), ScalarValue::null());
29        Ok(Some(ConstantArray::new(scalar, array.len()).into_array()))
30    }
31}
32
33register_kernel!(CastKernelAdapter(NullVTable).lift());
34
35#[cfg(test)]
36mod tests {
37    use rstest::rstest;
38    use vortex_dtype::DType;
39    use vortex_dtype::Nullability;
40    use vortex_dtype::PType;
41
42    use crate::arrays::NullArray;
43    use crate::compute::cast;
44    use crate::compute::conformance::cast::test_cast_conformance;
45
46    #[test]
47    fn test_cast_null_to_null() {
48        let null_array = NullArray::new(5);
49        let result = cast(null_array.as_ref(), &DType::Null).unwrap();
50        assert_eq!(result.len(), 5);
51        assert_eq!(result.dtype(), &DType::Null);
52    }
53
54    #[test]
55    fn test_cast_null_to_nullable_succeeds() {
56        let null_array = NullArray::new(5);
57        let result = cast(
58            null_array.as_ref(),
59            &DType::Primitive(PType::I32, Nullability::Nullable),
60        )
61        .unwrap();
62
63        // Should create a ConstantArray of nulls
64        assert_eq!(result.len(), 5);
65        assert_eq!(
66            result.dtype(),
67            &DType::Primitive(PType::I32, Nullability::Nullable)
68        );
69
70        // Verify all values are null
71        for i in 0..5 {
72            assert!(result.scalar_at(i).is_null());
73        }
74    }
75
76    #[test]
77    fn test_cast_null_to_non_nullable_fails() {
78        let null_array = NullArray::new(5);
79        let result = cast(
80            null_array.as_ref(),
81            &DType::Primitive(PType::I32, Nullability::NonNullable),
82        );
83        assert!(result.is_err());
84    }
85
86    #[rstest]
87    #[case(NullArray::new(5))]
88    #[case(NullArray::new(1))]
89    #[case(NullArray::new(100))]
90    #[case(NullArray::new(0))]
91    fn test_cast_null_conformance(#[case] array: NullArray) {
92        test_cast_conformance(array.as_ref());
93    }
94}