Skip to content

Commit 8df4c19

Browse files
committed
Attach RowFn validity directly to canonical output
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
1 parent 740cd82 commit 8df4c19

2 files changed

Lines changed: 50 additions & 3 deletions

File tree

vortex-array/src/scalar_fn/unstable/row/batch/execute/dense.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ use vortex_mask::MaskValuesRef;
88

99
use super::super::RowFnExecutionArgs;
1010
use super::super::args::BorrowedRowFnArgs;
11+
use crate::AnyCanonical;
1112
use crate::ArrayRef;
13+
use crate::Canonical;
1214
use crate::ExecutionCtx;
15+
use crate::IntoArray;
16+
use crate::arrays::masked::mask_validity_canonical;
1317
use crate::builtins::ArrayBuiltins;
1418
use crate::scalar_fn::unstable::row::execute::DenseAttempt;
1519
use crate::validity::Validity;
@@ -99,7 +103,20 @@ impl RowFnExecutionArgs {
99103
Validity::NonNullable | Validity::AllValid => {
100104
self.finalize_output(values, self.row_count)
101105
}
102-
Validity::Array(valid) => self.finalize_output(values.mask(valid)?, self.row_count),
106+
Validity::Array(validity_array) => {
107+
let values = if let Some(canonical) = values.as_opt::<AnyCanonical>() {
108+
mask_validity_canonical(
109+
Canonical::from(canonical),
110+
Validity::Array(validity_array),
111+
ctx,
112+
)?
113+
.into_array()
114+
} else {
115+
values.mask(validity_array)?
116+
};
117+
118+
self.finalize_output(values, self.row_count)
119+
}
103120
Validity::AllInvalid => {
104121
unreachable!("all-invalid validity is handled before dense row execution")
105122
}

vortex-array/src/scalar_fn/unstable/row/batch/tests.rs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ use crate::ExecutionCtx;
2020
use crate::IntoArray;
2121
use crate::VortexSessionExecute;
2222
use crate::array_session;
23+
#[cfg(not(codspeed))]
24+
use crate::arrays::Bool;
2325
use crate::arrays::BoolArray;
2426
use crate::arrays::ConstantArray;
2527
use crate::arrays::ExtensionArray;
2628
use crate::arrays::FixedSizeListArray;
29+
#[cfg(not(codspeed))]
30+
use crate::arrays::Primitive;
2731
use crate::arrays::PrimitiveArray;
2832
use crate::assert_arrays_eq;
2933
use crate::dtype::DType;
@@ -45,6 +49,8 @@ use crate::scalar_fn::unstable::row::RowFn;
4549
use crate::scalar_fn::unstable::row::RowVisitor;
4650
use crate::scalar_fn::unstable::row::execute_rows;
4751
use crate::scalar_fn::unstable::row::row_fn_return_dtype;
52+
#[cfg(not(codspeed))]
53+
use crate::test_harness::trace::trace_op;
4854
use crate::validity::Validity;
4955

5056
#[derive(Clone, Default)]
@@ -682,6 +688,7 @@ fn test_kernel_output_rejects_nulls_at_function_boundary() -> VortexResult<()> {
682688
Ok(())
683689
}
684690

691+
#[cfg(not(codspeed))]
685692
#[test]
686693
fn test_bool_output_builds_packed_values() -> VortexResult<()> {
687694
let input = PrimitiveArray::new(
@@ -692,10 +699,21 @@ fn test_bool_output_builds_packed_values() -> VortexResult<()> {
692699
let args = VecExecutionArgs::new(vec![input], 5);
693700
let mut ctx = array_session().create_execution_ctx();
694701

695-
let actual = execute_rows(&PackedPositive, &EmptyOptions, &args, &mut ctx)?;
702+
let traced = trace_op(|| execute_rows(&PackedPositive, &EmptyOptions, &args, &mut ctx))?;
703+
let actual = traced.output;
696704
let expected =
697705
BoolArray::from_iter([Some(true), Some(false), None, Some(false), Some(true)]).into_array();
698706

707+
assert!(
708+
actual.is::<Bool>(),
709+
"dense Boolean output must remain canonical, got {}",
710+
actual.encoding_id(),
711+
);
712+
let trace = traced.trace.to_string();
713+
assert!(
714+
!trace.contains("vortex.mask"),
715+
"dense canonical output must bypass the lazy mask path, got:\n{trace}",
716+
);
699717
assert_arrays_eq!(&actual, &expected, &mut ctx);
700718
Ok(())
701719
}
@@ -929,6 +947,7 @@ fn test_dense_retry_filters_when_direct_valid_rows_are_unavailable() -> VortexRe
929947
Ok(())
930948
}
931949

950+
#[cfg(not(codspeed))]
932951
#[test]
933952
fn test_deferred_owned_execution_does_not_retry_partially_valid_success() -> VortexResult<()> {
934953
let function = DeferredAdd::default();
@@ -938,9 +957,20 @@ fn test_deferred_owned_execution_does_not_retry_partially_valid_success() -> Vor
938957
let args = VecExecutionArgs::new(vec![lhs, rhs], 2);
939958
let mut ctx = array_session().create_execution_ctx();
940959

941-
let actual = execute_rows(&function, &EmptyOptions, &args, &mut ctx)?;
960+
let traced = trace_op(|| execute_rows(&function, &EmptyOptions, &args, &mut ctx))?;
961+
let actual = traced.output;
942962
let expected = PrimitiveArray::new(vec![2_i64, 0], validity).into_array();
943963

964+
assert!(
965+
actual.is::<Primitive>(),
966+
"dense primitive output must remain canonical, got {}",
967+
actual.encoding_id(),
968+
);
969+
let trace = traced.trace.to_string();
970+
assert!(
971+
!trace.contains("vortex.mask"),
972+
"dense canonical output must bypass the lazy mask path, got:\n{trace}",
973+
);
944974
assert_arrays_eq!(&actual, &expected, &mut ctx);
945975
assert_eq!(function.prepare_count(), 1);
946976
Ok(())

0 commit comments

Comments
 (0)