Skip to content

Commit c2e1605

Browse files
authored
fix: Validity::to_logical asserts mask length equals argument length (#2397)
I added an assertion to validity to_logical and fixed a bug which it found in VarBinViewArray's `take_into`.
1 parent 960acf6 commit c2e1605

File tree

5 files changed

+41
-9
lines changed

5 files changed

+41
-9
lines changed

encodings/sparse/src/compute/take.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ use crate::{SparseArray, SparseEncoding};
88
impl TakeFn<SparseArray> for SparseEncoding {
99
fn take(&self, array: &SparseArray, take_indices: &Array) -> VortexResult<Array> {
1010
let Some(new_patches) = array.patches().take(take_indices)? else {
11-
return Ok(ConstantArray::new(array.fill_scalar(), take_indices.len()).into_array());
11+
let result_nullability =
12+
array.dtype().nullability() | take_indices.dtype().nullability();
13+
let result_fill_scalar = array
14+
.fill_scalar()
15+
.cast(&array.dtype().with_nullability(result_nullability))?;
16+
return Ok(ConstantArray::new(result_fill_scalar, take_indices.len()).into_array());
1217
};
1318

1419
SparseArray::try_new_from_patches(new_patches, take_indices.len(), array.fill_scalar())

vortex-array/src/array/varbinview/compute/take.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl TakeFn<VarBinViewArray> for VarBinViewEncoding {
7878
// min-max valid range.
7979
// TODO(joe): impl validity_mask take
8080
let validity = array.validity().take(indices)?;
81-
let mask = validity.to_logical(array.len())?;
81+
let mask = validity.to_logical(indices.len())?;
8282
let indices = indices.clone().into_primitive()?;
8383

8484
match_each_integer_ptype!(indices.ptype(), |$I| {

vortex-array/src/compute/take.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,15 @@ pub fn take(array: impl AsRef<Array>, indices: impl AsRef<Array>) -> VortexResul
113113
#[cfg(debug_assertions)]
114114
{
115115
// If either the indices or the array are nullable, the result should be nullable.
116-
let expected_nullability =
117-
(indices.dtype().is_nullable() || array.dtype().is_nullable()).into();
116+
let expected_nullability = indices.dtype().nullability() | array.dtype().nullability();
118117
assert_eq!(
119118
taken.dtype(),
120119
&array.dtype().with_nullability(expected_nullability),
121-
"Take result should be nullable if either the indices or the array are nullable"
120+
"Take result ({}) should be nullable if either the indices ({}) or the array ({}) are nullable. ({})",
121+
taken.dtype(),
122+
indices.dtype().nullability().verbose_display(),
123+
array.dtype().nullability().verbose_display(),
124+
array.encoding(),
122125
);
123126
}
124127

@@ -136,12 +139,15 @@ pub fn take_into(
136139
#[cfg(debug_assertions)]
137140
{
138141
// If either the indices or the array are nullable, the result should be nullable.
139-
let expected_nullability =
140-
(indices.dtype().is_nullable() || array.dtype().is_nullable()).into();
142+
let expected_nullability = indices.dtype().nullability() | array.dtype().nullability();
141143
assert_eq!(
142144
builder.dtype(),
143145
&array.dtype().with_nullability(expected_nullability),
144-
"Take_into result should be nullable if either the indices or the array are nullable"
146+
"Take_into result ({}) should be nullable if, and only if, either the indices ({}) or the array ({}) are nullable. ({})",
147+
builder.dtype(),
148+
indices.dtype().nullability().verbose_display(),
149+
array.dtype().nullability().verbose_display(),
150+
array.encoding(),
145151
);
146152
}
147153

vortex-array/src/validity.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,16 @@ impl Validity {
300300
Ok(match self {
301301
Self::NonNullable | Self::AllValid => Mask::AllTrue(length),
302302
Self::AllInvalid => Mask::AllFalse(length),
303-
Self::Array(a) => Mask::try_from(a.clone())?,
303+
Self::Array(is_valid) => {
304+
assert_eq!(
305+
is_valid.len(),
306+
length,
307+
"Validity::Array length must equal to_logical's argument: {}, {}.",
308+
is_valid.len(),
309+
length,
310+
);
311+
Mask::try_from(is_valid.clone())?
312+
}
304313
})
305314
}
306315

vortex-dtype/src/nullability.rs

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ pub enum Nullability {
1111
Nullable,
1212
}
1313

14+
impl Nullability {
15+
/// A self-describing displayed form.
16+
///
17+
/// The usual Display renders [Nullability::NonNullable] as the empty string.
18+
pub fn verbose_display(&self) -> impl Display {
19+
match self {
20+
Nullability::NonNullable => "NonNullable",
21+
Nullability::Nullable => "Nullable",
22+
}
23+
}
24+
}
25+
1426
impl BitOr for Nullability {
1527
type Output = Nullability;
1628

0 commit comments

Comments
 (0)