@@ -25,7 +25,10 @@ use crate::arrays::ConstantArray;
2525use crate :: arrays:: ExtensionArray ;
2626use crate :: arrays:: FixedSizeListArray ;
2727use crate :: arrays:: PrimitiveArray ;
28+ use crate :: arrays:: VarBinViewArray ;
29+ use crate :: arrays:: varbinview:: BinaryView ;
2830use crate :: assert_arrays_eq;
31+ use crate :: buffer:: BufferHandle ;
2932use crate :: dtype:: DType ;
3033use crate :: dtype:: NativePType ;
3134use crate :: dtype:: Nullability ;
@@ -43,6 +46,8 @@ use crate::scalar_fn::unstable::row::OutputElement;
4346use crate :: scalar_fn:: unstable:: row:: OutputSink ;
4447use crate :: scalar_fn:: unstable:: row:: RowFn ;
4548use crate :: scalar_fn:: unstable:: row:: RowVisitor ;
49+ use crate :: scalar_fn:: unstable:: row:: Utf8Column ;
50+ use crate :: scalar_fn:: unstable:: row:: execute:: execute_bool_dense_attempt;
4651use crate :: scalar_fn:: unstable:: row:: execute_rows;
4752use crate :: scalar_fn:: unstable:: row:: row_fn_return_dtype;
4853use crate :: validity:: Validity ;
@@ -83,6 +88,20 @@ struct PackedGreaterThan<const MULTIVERSIONED: bool>;
8388#[ derive( Clone ) ]
8489struct DeferredGreaterThan < const MULTIVERSIONED : bool > ;
8590
91+ #[ derive( Clone , Copy ) ]
92+ enum BooleanInputShape {
93+ Columns ,
94+ ConstantLhs ,
95+ ConstantRhs ,
96+ }
97+
98+ #[ derive( Clone , Copy ) ]
99+ enum BooleanValidity {
100+ AllValid ,
101+ AllNull ,
102+ Partial ,
103+ }
104+
86105#[ derive( Clone ) ]
87106struct ValidOnlyPositive ;
88107
@@ -866,6 +885,100 @@ fn test_deferred_bool_output_handles_partial_constants() -> VortexResult<()> {
866885 Ok ( ( ) )
867886}
868887
888+ #[ rstest]
889+ #[ case:: empty( 0 ) ]
890+ #[ case:: one( 1 ) ]
891+ #[ case:: word_tail( 63 ) ]
892+ #[ case:: word( 64 ) ]
893+ #[ case:: word_remainder( 65 ) ]
894+ #[ case:: multiword( 130 ) ]
895+ fn test_deferred_bool_sliced_validity_and_constants (
896+ #[ case] len : usize ,
897+ #[ values( false , true ) ] multiversioned : bool ,
898+ #[ values(
899+ BooleanInputShape :: Columns ,
900+ BooleanInputShape :: ConstantLhs ,
901+ BooleanInputShape :: ConstantRhs
902+ ) ]
903+ input_shape : BooleanInputShape ,
904+ #[ values(
905+ BooleanValidity :: AllValid ,
906+ BooleanValidity :: AllNull ,
907+ BooleanValidity :: Partial
908+ ) ]
909+ validity_pattern : BooleanValidity ,
910+ ) -> VortexResult < ( ) > {
911+ let valid = |index : usize | match validity_pattern {
912+ BooleanValidity :: AllValid => true ,
913+ BooleanValidity :: AllNull => false ,
914+ BooleanValidity :: Partial => !index. is_multiple_of ( 3 ) ,
915+ } ;
916+ let validity = Validity :: Array ( BoolArray :: from_iter ( ( 0 ..len + 2 ) . map ( valid) ) . into_array ( ) ) ;
917+ let varying = PrimitiveArray :: new (
918+ ( 0 ..len + 2 )
919+ . map ( |index| if valid ( index) { index as i64 } else { i64:: MIN } )
920+ . collect :: < Vec < _ > > ( ) ,
921+ validity,
922+ )
923+ . into_array ( )
924+ . slice ( 1 ..len + 1 ) ?;
925+ let constant = ConstantArray :: new ( 32_i64 , len) . into_array ( ) ;
926+ let other = PrimitiveArray :: from_iter ( std:: iter:: repeat_n ( 32_i64 , len) ) . into_array ( ) ;
927+ let ( lhs, rhs) = match input_shape {
928+ BooleanInputShape :: Columns => ( varying, other) ,
929+ BooleanInputShape :: ConstantLhs => ( constant, varying) ,
930+ BooleanInputShape :: ConstantRhs => ( varying, constant) ,
931+ } ;
932+ let args = VecExecutionArgs :: new ( vec ! [ lhs, rhs] , len) ;
933+ let mut ctx = array_session ( ) . create_execution_ctx ( ) ;
934+ let actual = if multiversioned {
935+ execute_rows ( & DeferredGreaterThan :: < true > , & EmptyOptions , & args, & mut ctx) ?
936+ } else {
937+ execute_rows (
938+ & DeferredGreaterThan :: < false > ,
939+ & EmptyOptions ,
940+ & args,
941+ & mut ctx,
942+ ) ?
943+ } ;
944+ let expected = BoolArray :: from_iter ( ( 1 ..len + 1 ) . map ( |index| {
945+ valid ( index) . then_some ( if matches ! ( input_shape, BooleanInputShape :: ConstantLhs ) {
946+ 32 > index as i64
947+ } else {
948+ index as i64 > 32
949+ } )
950+ } ) )
951+ . into_array ( ) ;
952+ assert_arrays_eq ! ( & actual, & expected, & mut ctx) ;
953+ Ok ( ( ) )
954+ }
955+
956+ #[ test]
957+ fn test_deferred_bool_decode_error_is_terminal ( ) {
958+ let views = Buffer :: from ( vec ! [ BinaryView :: make_view( & [ 0xff ] , 0 , 0 ) ] ) ;
959+ let input = VarBinViewArray :: new_handle (
960+ BufferHandle :: new_host ( views. into_byte_buffer ( ) ) ,
961+ Default :: default ( ) ,
962+ DType :: Utf8 ( Nullability :: NonNullable ) ,
963+ Validity :: NonNullable ,
964+ )
965+ . into_array ( ) ;
966+ let args = VecExecutionArgs :: new ( vec ! [ input] , 1 ) ;
967+ let mut ctx = array_session ( ) . create_execution_ctx ( ) ;
968+
969+ let result = execute_bool_dense_attempt :: < ( Utf8Column , ) , ( ) , bool , true > (
970+ & args,
971+ & mut ctx,
972+ |_| ( ) ,
973+ |& ( ) , ( value, ) | ( !value. is_empty ( ) , false ) ,
974+ |_| Ok ( ( ) ) ,
975+ ) ;
976+ assert ! (
977+ result. is_err( ) ,
978+ "a decode error must not become a deferred row error"
979+ ) ;
980+ }
981+
869982#[ test]
870983fn test_deferred_bool_output_reports_valid_row_failure ( ) -> VortexResult < ( ) > {
871984 let lhs = PrimitiveArray :: from_iter ( [ 1_i64 , i64:: MIN , -1 ] ) . into_array ( ) ;
0 commit comments