@@ -53,6 +53,7 @@ use datafusion_functions_aggregate_common::aggregate::groups_accumulator::accumu
5353use datafusion_functions_aggregate_common:: aggregate:: groups_accumulator:: nulls:: filtered_null_mask;
5454use datafusion_functions_aggregate_common:: utils:: GenericDistinctBuffer ;
5555use datafusion_macros:: user_doc;
56+ use std:: collections:: HashMap ;
5657
5758make_udaf_expr_and_func ! (
5859 Median ,
@@ -298,15 +299,35 @@ impl<T: ArrowNumericType> Accumulator for MedianAccumulator<T> {
298299 }
299300
300301 fn retract_batch ( & mut self , values : & [ ArrayRef ] ) -> Result < ( ) > {
301- let values = values[ 0 ] . as_primitive :: < T > ( ) ;
302- for v in values. iter ( ) . flatten ( ) {
303- if let Some ( idx) = self . all_values . iter ( ) . position ( |x| * x == v) {
304- self . all_values . swap_remove ( idx) ;
305- } else {
306- return Err ( internal_datafusion_err ! (
307- "attempted to retract value {v:?} that was not present"
308- ) ) ;
302+ let mut to_remove: HashMap < ScalarValue , usize > = HashMap :: new ( ) ;
303+
304+ let arr = & values[ 0 ] ;
305+ for i in 0 ..arr. len ( ) {
306+ let v = ScalarValue :: try_from_array ( arr, i) ?;
307+ if !v. is_null ( ) {
308+ * to_remove. entry ( v) . or_default ( ) += 1 ;
309+ }
310+ }
311+
312+ let mut i = 0 ;
313+ while i < self . all_values . len ( ) {
314+ let k = ScalarValue :: new_primitive :: < T > (
315+ Some ( self . all_values [ i] ) ,
316+ & self . data_type ,
317+ ) ?;
318+ if let Some ( count) = to_remove. get_mut ( & k)
319+ && * count > 0
320+ {
321+ self . all_values . swap_remove ( i) ;
322+ * count -= 1 ;
323+ if * count == 0 {
324+ to_remove. remove ( & k) ;
325+ if to_remove. is_empty ( ) {
326+ break ;
327+ }
328+ }
309329 }
330+ i += 1 ;
310331 }
311332 Ok ( ( ) )
312333 }
0 commit comments