Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions vortex-array/src/array/erased.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ impl ArrayRef {

/// Returns whether all items in the array are valid.
pub fn all_valid(&self, ctx: &mut ExecutionCtx) -> VortexResult<bool> {
if self.is_empty() {
return Ok(true);
}

match self.validity()? {
Validity::NonNullable | Validity::AllValid => Ok(true),
Validity::AllInvalid => Ok(false),
Expand All @@ -310,6 +314,10 @@ impl ArrayRef {

/// Returns whether the array is all invalid.
pub fn all_invalid(&self, ctx: &mut ExecutionCtx) -> VortexResult<bool> {
if self.is_empty() {
return Ok(true);
}

match self.validity()? {
Validity::NonNullable | Validity::AllValid => Ok(false),
Validity::AllInvalid => Ok(true),
Expand Down
21 changes: 21 additions & 0 deletions vortex-array/src/arrays/masked/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// SPDX-FileCopyrightText: Copyright the Vortex contributors

use rstest::rstest;
use vortex_buffer::BitBuffer;
use vortex_buffer::Buffer;
use vortex_error::VortexExpect;
use vortex_error::VortexResult;

Expand All @@ -10,6 +12,7 @@ use crate::Canonical;
use crate::IntoArray;
use crate::VortexSessionExecute;
use crate::array_session;
use crate::arrays::BoolArray;
use crate::arrays::ListViewArray;
use crate::arrays::PrimitiveArray;
use crate::assert_arrays_eq;
Expand Down Expand Up @@ -41,6 +44,24 @@ fn test_dtype_nullability_with_nullable_child() {
assert!(child.dtype().is_nullable());
}

#[test]
fn test_empty_child_with_array_validity() -> VortexResult<()> {
let child_validity =
Validity::Array(BoolArray::new(BitBuffer::new_set(0), Validity::NonNullable).into_array());
let child = PrimitiveArray::new(Buffer::<i32>::empty(), child_validity).into_array();
let validity =
Validity::Array(BoolArray::new(BitBuffer::new_set(0), Validity::NonNullable).into_array());

let mut ctx = array_session().create_execution_ctx();
assert!(child.all_valid(&mut ctx)?);
assert!(child.all_invalid(&mut ctx)?);

let array = MaskedArray::try_new(child, validity)?;

assert!(array.is_empty());
Ok(())
}

#[test]
fn test_canonical_dtype_matches_array_dtype() -> VortexResult<()> {
// The canonical form should have the same nullability as the array's dtype.
Expand Down
5 changes: 5 additions & 0 deletions vortex-array/src/arrays/masked/vtable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ impl VTable for Masked {
*ID
}

#[expect(clippy::disallowed_methods)]
fn validate(
&self,
_data: &MaskedData,
Expand All @@ -92,6 +93,10 @@ impl VTable for Masked {
child.dtype().as_nullable() == *dtype,
"MaskedArray dtype does not match child and validity"
);
vortex_ensure!(
child.all_valid(&mut legacy_session().create_execution_ctx())?,
"MaskedArray children must not have nulls",
);
Ok(())
}

Expand Down
Loading