@@ -11,6 +11,7 @@ use vortex_array::arrays::PrimitiveArray;
1111use vortex_array:: arrays:: VarBinArray ;
1212use vortex_array:: arrays:: VarBinViewArray ;
1313use vortex_array:: arrays:: filter:: FilterKernel ;
14+ use vortex_array:: assert_arrays_eq;
1415use vortex_array:: dtype:: DType ;
1516use vortex_array:: dtype:: Nullability ;
1617use vortex_array:: dtype:: PType ;
@@ -245,6 +246,34 @@ fn test_onpair_empty() -> vortex_error::VortexResult<()> {
245246 Ok ( ( ) )
246247}
247248
249+ /// All-null input has no training values, but still produces a valid OnPair
250+ /// array backed by an empty code stream and `len + 1` zero boundaries.
251+ #[ cfg_attr( miri, ignore) ]
252+ #[ test]
253+ fn test_onpair_all_null ( ) -> vortex_error:: VortexResult < ( ) > {
254+ let input = VarBinArray :: from_iter (
255+ [ None :: < & str > , None , None ] ,
256+ DType :: Utf8 ( Nullability :: Nullable ) ,
257+ )
258+ . into_array ( ) ;
259+ let mut ctx = SESSION . create_execution_ctx ( ) ;
260+ let arr = onpair_compress ( & input, DEFAULT_DICT12_CONFIG , & mut ctx) ?;
261+
262+ assert ! ( arr. codes( ) . is_empty( ) ) ;
263+ let codes_offsets = arr
264+ . codes_offsets ( )
265+ . clone ( )
266+ . execute :: < PrimitiveArray > ( & mut ctx) ?;
267+ assert_eq ! ( codes_offsets. as_slice:: <u32 >( ) , & [ 0 , 0 , 0 , 0 ] ) ;
268+ let uncompressed_lengths = arr
269+ . uncompressed_lengths ( )
270+ . clone ( )
271+ . execute :: < PrimitiveArray > ( & mut ctx) ?;
272+ assert_eq ! ( uncompressed_lengths. as_slice:: <i32 >( ) , & [ 0 , 0 , 0 ] ) ;
273+ assert_arrays_eq ! ( arr. into_array( ) , input, & mut ctx) ;
274+ Ok ( ( ) )
275+ }
276+
248277/// Filter must share the dictionary — never recompress (this is the
249278/// regression cause on TPC-H Q22 SF=10). Exercise both selectivities
250279/// and check that the result is bit-exact and still an OnPairArray.
0 commit comments