Skip to content

Commit efa9f4d

Browse files
authored
feat: teach constant to fill_null (#4985)
Does what it says on the tin. --------- Signed-off-by: Daniel King <[email protected]>
1 parent 3e79554 commit efa9f4d

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use vortex_error::VortexResult;
5+
use vortex_scalar::Scalar;
6+
7+
use crate::arrays::{ConstantArray, ConstantVTable};
8+
use crate::compute::{FillNullKernel, FillNullKernelAdapter, cast};
9+
use crate::{ArrayRef, IntoArray, register_kernel};
10+
11+
impl FillNullKernel for ConstantVTable {
12+
fn fill_null(&self, array: &ConstantArray, fill_value: &Scalar) -> VortexResult<ArrayRef> {
13+
if array.scalar().is_null() {
14+
Ok(ConstantArray::new(fill_value.clone(), array.len()).into_array())
15+
} else {
16+
cast(array.as_ref(), fill_value.dtype())
17+
}
18+
}
19+
}
20+
21+
register_kernel!(FillNullKernelAdapter(ConstantVTable).lift());
22+
23+
#[cfg(test)]
24+
mod test {
25+
use vortex_scalar::Scalar;
26+
27+
use crate::IntoArray as _;
28+
use crate::arrays::ConstantArray;
29+
use crate::arrow::IntoArrowArray as _;
30+
use crate::compute::fill_null;
31+
32+
#[test]
33+
fn test_null() {
34+
let actual = fill_null(
35+
&ConstantArray::new(Scalar::from(None::<i32>), 3).into_array(),
36+
&Scalar::from(1),
37+
)
38+
.unwrap();
39+
let expected = ConstantArray::new(Scalar::from(1), 3).into_array();
40+
41+
assert!(!actual.dtype().is_nullable());
42+
43+
let actual_arrow = actual.clone().into_arrow_preferred().unwrap();
44+
let expected_arrow = expected.clone().into_arrow_preferred().unwrap();
45+
assert_eq!(
46+
&actual_arrow,
47+
&expected_arrow,
48+
"{}, {}",
49+
actual.display_values(),
50+
expected.display_values()
51+
);
52+
}
53+
54+
#[test]
55+
fn test_non_null() {
56+
let actual = fill_null(
57+
&ConstantArray::new(Scalar::from(Some(1)), 3).into_array(),
58+
&Scalar::from(1),
59+
)
60+
.unwrap();
61+
let expected = ConstantArray::new(Scalar::from(1), 3).into_array();
62+
63+
assert!(!actual.dtype().is_nullable());
64+
65+
let actual_arrow = actual.clone().into_arrow_preferred().unwrap();
66+
let expected_arrow = expected.clone().into_arrow_preferred().unwrap();
67+
assert_eq!(
68+
&actual_arrow,
69+
&expected_arrow,
70+
"{}, {}",
71+
actual.display_values(),
72+
expected.display_values()
73+
);
74+
}
75+
76+
#[test]
77+
fn test_non_nullable_with_nullable() {
78+
let actual = fill_null(
79+
&ConstantArray::new(Scalar::from(1), 3).into_array(),
80+
&Scalar::from(Some(1)),
81+
)
82+
.unwrap();
83+
let expected = ConstantArray::new(Scalar::from(1), 3).into_array();
84+
85+
assert!(!Scalar::from(1).dtype().is_nullable());
86+
87+
assert!(actual.dtype().is_nullable());
88+
89+
let actual_arrow = actual.clone().into_arrow_preferred().unwrap();
90+
let expected_arrow = expected.clone().into_arrow_preferred().unwrap();
91+
assert_eq!(
92+
&actual_arrow,
93+
&expected_arrow,
94+
"{}, {}",
95+
actual.display_values(),
96+
expected.display_values()
97+
);
98+
}
99+
}

vortex-array/src/arrays/constant/compute/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod binary_numeric;
55
mod boolean;
66
mod cast;
77
mod compare;
8+
mod fill_null;
89
mod filter;
910
mod invert;
1011
mod mask;

vortex-array/src/compute/fill_null.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ pub(crate) fn warm_up_vtable() -> usize {
2424
FILL_NULL_FN.kernels().len()
2525
}
2626

27+
/// Replace nulls in the array with another value.
28+
///
29+
/// # Examples
30+
///
31+
/// ```
32+
/// use vortex_array::arrays::{PrimitiveArray};
33+
/// use vortex_array::compute::{fill_null};
34+
/// use vortex_scalar::Scalar;
35+
///
36+
/// let array =
37+
/// PrimitiveArray::from_option_iter([Some(0i32), None, Some(1i32), None, Some(2i32)]);
38+
/// let array = fill_null(array.as_ref(), &Scalar::from(42i32)).unwrap();
39+
/// assert_eq!(array.display_values().to_string(), "[0i32, 42i32, 1i32, 42i32, 2i32]");
40+
/// ```
2741
pub fn fill_null(array: &dyn Array, fill_value: &Scalar) -> VortexResult<ArrayRef> {
2842
FILL_NULL_FN
2943
.invoke(&InvocationArgs {

0 commit comments

Comments
 (0)