vortex_sparse/compute/
fill_null.rs1use vortex_array::ArrayRef;
5use vortex_array::ArrayView;
6use vortex_array::ExecutionCtx;
7use vortex_array::IntoArray;
8use vortex_array::builtins::ArrayBuiltins;
9use vortex_array::scalar::Scalar;
10use vortex_array::scalar_fn::fns::fill_null::FillNullKernel;
11use vortex_error::VortexResult;
12
13use crate::Sparse;
14use crate::SparseExt as _;
15
16impl FillNullKernel for Sparse {
22 fn fill_null(
23 array: ArrayView<'_, Self>,
24 fill_value: &Scalar,
25 _ctx: &mut ExecutionCtx,
26 ) -> VortexResult<Option<ArrayRef>> {
27 let new_fill = if array.fill_scalar().is_null() {
28 fill_value.clone()
29 } else {
30 array.fill_scalar().cast(fill_value.dtype())?
31 };
32
33 let new_patches = array
34 .patches()
35 .map_values(|values| values.fill_null(fill_value.clone()))?;
36
37 Ok(Some(
38 Sparse::try_new_from_patches(new_patches, new_fill)?.into_array(),
39 ))
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use std::sync::LazyLock;
46
47 use rstest::rstest;
48 use vortex_array::Canonical;
49 use vortex_array::IntoArray;
50 use vortex_array::VortexSessionExecute;
51 use vortex_array::arrays::PrimitiveArray;
52 use vortex_array::assert_arrays_eq;
53 use vortex_array::builtins::ArrayBuiltins;
54 use vortex_array::dtype::DType;
55 use vortex_array::dtype::Nullability;
56 use vortex_array::dtype::PType;
57 use vortex_array::scalar::Scalar;
58 use vortex_array::session::ArraySession;
59 use vortex_buffer::buffer;
60 use vortex_session::VortexSession;
61
62 use crate::Sparse;
63 use crate::initialize;
64
65 static SESSION: LazyLock<VortexSession> = LazyLock::new(|| {
66 let session = VortexSession::empty().with::<ArraySession>();
67 initialize(&session);
68 session
69 });
70
71 fn nullable_i32() -> DType {
72 DType::Primitive(PType::I32, Nullability::Nullable)
73 }
74
75 #[rstest]
76 #[case(Sparse::try_new(
78 buffer![1u64, 3, 5].into_array(),
79 PrimitiveArray::from_option_iter([Some(10i32), None, Some(30)]).into_array().cast(nullable_i32()).unwrap(),
80 8,
81 Scalar::null(nullable_i32()),
82 ).unwrap().into_array())]
83 #[case(Sparse::try_new(
85 buffer![0u64, 2].into_array(),
86 PrimitiveArray::from_option_iter([Some(7i32), None]).into_array().cast(nullable_i32()).unwrap(),
87 4,
88 Scalar::from(1i32).cast(&nullable_i32()).unwrap(),
89 ).unwrap().into_array())]
90 fn fill_null_matches_canonical(#[case] array: vortex_array::ArrayRef) {
91 let mut ctx = SESSION.create_execution_ctx();
92 let fill = Scalar::from(0i32);
93
94 let kernel = array
96 .fill_null(fill.clone())
97 .unwrap()
98 .execute::<Canonical>(&mut ctx)
99 .unwrap();
100
101 let canonical_input = array.execute::<Canonical>(&mut ctx).unwrap().into_array();
103 let baseline = canonical_input
104 .fill_null(fill)
105 .unwrap()
106 .execute::<Canonical>(&mut ctx)
107 .unwrap();
108
109 assert_arrays_eq!(kernel, baseline);
110 }
111}