@@ -13,6 +13,7 @@ use std::fmt::Formatter;
1313
1414use vortex_error:: VortexExpect ;
1515use vortex_error:: VortexResult ;
16+ use vortex_mask:: Mask ;
1617use vortex_session:: registry:: CachedId ;
1718
1819use self :: bool:: check_bool_sorted;
@@ -41,6 +42,44 @@ use crate::expr::stats::Stat;
4142use crate :: expr:: stats:: StatsProviderExt ;
4243use crate :: scalar:: Scalar ;
4344
45+ fn check_fixed_size_binary_sorted (
46+ array : & crate :: arrays:: FixedSizeBinaryArray ,
47+ strict : bool ,
48+ ctx : & mut ExecutionCtx ,
49+ ) -> VortexResult < bool > {
50+ let DType :: FixedSizeBinary ( byte_width, _) = array. dtype ( ) else {
51+ unreachable ! ( )
52+ } ;
53+ let byte_width = * byte_width as usize ;
54+ let values = array. buffer_handle ( ) . to_host_sync ( ) ;
55+ let validity = array. as_ref ( ) . validity ( ) ?. execute_mask ( array. len ( ) , ctx) ?;
56+ let mut valid = match & validity {
57+ Mask :: AllTrue ( len) => {
58+ Box :: new ( std:: iter:: repeat_n ( true , * len) ) as Box < dyn Iterator < Item = bool > >
59+ }
60+ Mask :: AllFalse ( len) => Box :: new ( std:: iter:: repeat_n ( false , * len) ) ,
61+ Mask :: Values ( values) => Box :: new ( values. bit_buffer ( ) . iter ( ) ) ,
62+ } ;
63+ let mut previous: Option < Option < & [ u8 ] > > = None ;
64+ for index in 0 ..array. len ( ) {
65+ let current = valid. next ( ) . unwrap_or ( false ) . then ( || {
66+ let start = index * byte_width;
67+ & values[ start..start + byte_width]
68+ } ) ;
69+ if let Some ( previous) = previous
70+ && if strict {
71+ previous >= current
72+ } else {
73+ previous > current
74+ }
75+ {
76+ return Ok ( false ) ;
77+ }
78+ previous = Some ( current) ;
79+ }
80+ Ok ( true )
81+ }
82+
4483/// Options for the `is_sorted` aggregate function.
4584#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
4685pub struct IsSortedOptions {
@@ -254,7 +293,8 @@ impl AggregateFnVTable for IsSorted {
254293 | DType :: Primitive ( ..)
255294 | DType :: Decimal ( ..)
256295 | DType :: Utf8 ( _)
257- | DType :: Binary ( _) => Some ( DType :: Bool ( Nullability :: NonNullable ) ) ,
296+ | DType :: Binary ( _)
297+ | DType :: FixedSizeBinary ( ..) => Some ( DType :: Bool ( Nullability :: NonNullable ) ) ,
258298 }
259299 }
260300
@@ -271,7 +311,8 @@ impl AggregateFnVTable for IsSorted {
271311 | DType :: Primitive ( ..)
272312 | DType :: Decimal ( ..)
273313 | DType :: Utf8 ( _)
274- | DType :: Binary ( _) => Some ( make_is_sorted_partial_dtype ( input_dtype) ) ,
314+ | DType :: Binary ( _)
315+ | DType :: FixedSizeBinary ( ..) => Some ( make_is_sorted_partial_dtype ( input_dtype) ) ,
275316 }
276317 }
277318
@@ -487,10 +528,13 @@ impl AggregateFnVTable for IsSorted {
487528
488529 // Check within-batch sortedness.
489530 let batch_is_sorted = match c {
490- Canonical :: Primitive ( p) => check_primitive_sorted ( p, partial. strict , ctx) ?,
531+ Canonical :: Primitive ( a) => check_primitive_sorted ( a, partial. strict , ctx) ?,
532+ Canonical :: Decimal ( a) => check_decimal_sorted ( a, partial. strict , ctx) ?,
533+ Canonical :: FixedSizeBinary ( a) => {
534+ check_fixed_size_binary_sorted ( a, partial. strict , ctx) ?
535+ }
491536 Canonical :: Bool ( b) => check_bool_sorted ( b, partial. strict , ctx) ?,
492537 Canonical :: VarBinView ( v) => check_varbinview_sorted ( v, partial. strict , ctx) ?,
493- Canonical :: Decimal ( d) => check_decimal_sorted ( d, partial. strict , ctx) ?,
494538 Canonical :: Extension ( e) => check_extension_sorted ( e, partial. strict , ctx) ?,
495539 Canonical :: Null ( _) => !partial. strict ,
496540 // Struct, List, FixedSizeList should have been filtered out by return_dtype
0 commit comments