@@ -175,6 +175,19 @@ impl Scan {
175175 }
176176}
177177
178+ fn reduce_ndv_by_datum_range ( ndv : Ndv , min : & Datum , max : & Datum ) -> Ndv {
179+ match ( max, min) {
180+ ( Datum :: UInt ( m) , Datum :: UInt ( n) ) if m >= n => {
181+ ndv. reduce ( m. saturating_sub ( * n) . saturating_add ( 1 ) as _ )
182+ }
183+ ( Datum :: Int ( m) , Datum :: Int ( n) ) if m >= n => {
184+ ndv. reduce ( m. saturating_add ( 1 ) . saturating_sub ( * n) as _ )
185+ }
186+ _ if max == min => Ndv :: Stat ( 1.0 ) ,
187+ _ => ndv,
188+ }
189+ }
190+
178191impl PartialEq for Scan {
179192 fn eq ( & self , other : & Self ) -> bool {
180193 self . table_index == other. table_index
@@ -282,14 +295,7 @@ impl Operator for Scan {
282295 } ;
283296
284297 // Alter ndv based on min and max if the datum is uint or int.
285- let ndv = match ( & max, & min) {
286- ( Datum :: UInt ( m) , Datum :: UInt ( n) ) if m >= n => ndv. reduce ( ( m - n + 1 ) as _ ) ,
287- ( Datum :: Int ( m) , Datum :: Int ( n) ) if m >= n => {
288- ndv. reduce ( m. saturating_add ( 1 ) . saturating_sub ( * n) as _ )
289- }
290- _ if max == min => Ndv :: Stat ( 1.0 ) ,
291- _ => ndv,
292- } ;
298+ let ndv = reduce_ndv_by_datum_range ( ndv, & min, & max) ;
293299
294300 let histogram = if let Some ( histogram) = self . statistics . histograms . get ( k)
295301 && histogram. is_some ( )
@@ -367,3 +373,19 @@ impl Operator for Scan {
367373 ) )
368374 }
369375}
376+
377+ #[ cfg( test) ]
378+ mod tests {
379+ use super :: * ;
380+
381+ #[ test]
382+ fn test_reduce_ndv_by_uint_full_range_saturates ( ) {
383+ let reduced = reduce_ndv_by_datum_range (
384+ Ndv :: Stat ( ( u64:: MAX as f64 ) + 1.0 ) ,
385+ & Datum :: UInt ( 0 ) ,
386+ & Datum :: UInt ( u64:: MAX ) ,
387+ ) ;
388+
389+ assert_eq ! ( reduced. value( ) , u64 :: MAX as f64 ) ;
390+ }
391+ }
0 commit comments