@@ -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;
@@ -31,6 +32,7 @@ use crate::aggregate_fn::AggregateFnVTable;
3132use crate :: aggregate_fn:: DynAccumulator ;
3233use crate :: arrays:: Constant ;
3334use crate :: arrays:: Null ;
35+ use crate :: arrays:: fixed_size_binary:: FixedSizeBinaryArrayExt ;
3436use crate :: builtins:: ArrayBuiltins ;
3537use crate :: dtype:: DType ;
3638use crate :: dtype:: FieldNames ;
@@ -41,6 +43,44 @@ use crate::expr::stats::Stat;
4143use crate :: expr:: stats:: StatsProviderExt ;
4244use crate :: scalar:: Scalar ;
4345
46+ fn check_fixed_size_binary_sorted (
47+ array : & crate :: arrays:: FixedSizeBinaryArray ,
48+ strict : bool ,
49+ ctx : & mut ExecutionCtx ,
50+ ) -> VortexResult < bool > {
51+ let DType :: FixedSizeBinary ( byte_width, _) = array. dtype ( ) else {
52+ unreachable ! ( )
53+ } ;
54+ let byte_width = * byte_width as usize ;
55+ let values = array. buffer_handle ( ) . to_host_sync ( ) ;
56+ let validity = array. as_ref ( ) . validity ( ) ?. execute_mask ( array. len ( ) , ctx) ?;
57+ let mut valid = match & validity {
58+ Mask :: AllTrue ( len) => {
59+ Box :: new ( std:: iter:: repeat_n ( true , * len) ) as Box < dyn Iterator < Item = bool > >
60+ }
61+ Mask :: AllFalse ( len) => Box :: new ( std:: iter:: repeat_n ( false , * len) ) ,
62+ Mask :: Values ( values) => Box :: new ( values. bit_buffer ( ) . iter ( ) ) ,
63+ } ;
64+ let mut previous: Option < Option < & [ u8 ] > > = None ;
65+ for index in 0 ..array. len ( ) {
66+ let current = valid. next ( ) . unwrap_or ( false ) . then ( || {
67+ let start = index * byte_width;
68+ & values[ start..start + byte_width]
69+ } ) ;
70+ if let Some ( previous) = previous
71+ && if strict {
72+ previous >= current
73+ } else {
74+ previous > current
75+ }
76+ {
77+ return Ok ( false ) ;
78+ }
79+ previous = Some ( current) ;
80+ }
81+ Ok ( true )
82+ }
83+
4484/// Options for the `is_sorted` aggregate function.
4585#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
4686pub struct IsSortedOptions {
@@ -254,7 +294,8 @@ impl AggregateFnVTable for IsSorted {
254294 | DType :: Primitive ( ..)
255295 | DType :: Decimal ( ..)
256296 | DType :: Utf8 ( _)
257- | DType :: Binary ( _) => Some ( DType :: Bool ( Nullability :: NonNullable ) ) ,
297+ | DType :: Binary ( _)
298+ | DType :: FixedSizeBinary ( ..) => Some ( DType :: Bool ( Nullability :: NonNullable ) ) ,
258299 }
259300 }
260301
@@ -271,7 +312,8 @@ impl AggregateFnVTable for IsSorted {
271312 | DType :: Primitive ( ..)
272313 | DType :: Decimal ( ..)
273314 | DType :: Utf8 ( _)
274- | DType :: Binary ( _) => Some ( make_is_sorted_partial_dtype ( input_dtype) ) ,
315+ | DType :: Binary ( _)
316+ | DType :: FixedSizeBinary ( ..) => Some ( make_is_sorted_partial_dtype ( input_dtype) ) ,
275317 }
276318 }
277319
@@ -487,10 +529,13 @@ impl AggregateFnVTable for IsSorted {
487529
488530 // Check within-batch sortedness.
489531 let batch_is_sorted = match c {
490- Canonical :: Primitive ( p) => check_primitive_sorted ( p, partial. strict , ctx) ?,
532+ Canonical :: Primitive ( a) => check_primitive_sorted ( a, partial. strict , ctx) ?,
533+ Canonical :: Decimal ( a) => check_decimal_sorted ( a, partial. strict , ctx) ?,
534+ Canonical :: FixedSizeBinary ( a) => {
535+ check_fixed_size_binary_sorted ( a, partial. strict , ctx) ?
536+ }
491537 Canonical :: Bool ( b) => check_bool_sorted ( b, partial. strict , ctx) ?,
492538 Canonical :: VarBinView ( v) => check_varbinview_sorted ( v, partial. strict , ctx) ?,
493- Canonical :: Decimal ( d) => check_decimal_sorted ( d, partial. strict , ctx) ?,
494539 Canonical :: Extension ( e) => check_extension_sorted ( e, partial. strict , ctx) ?,
495540 Canonical :: Null ( _) => !partial. strict ,
496541 // Struct, List, FixedSizeList should have been filtered out by return_dtype
0 commit comments