@@ -20,6 +20,14 @@ use databend_common_exception::ErrorCode;
2020
2121pub type F64 = OrderedFloat < f64 > ;
2222
23+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
24+ pub enum DatumKind {
25+ Int ,
26+ UInt ,
27+ Float ,
28+ Bytes ,
29+ }
30+
2331#[ derive( serde:: Serialize , serde:: Deserialize , Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
2432pub enum Datum {
2533 Bool ( bool ) ,
@@ -34,14 +42,6 @@ impl Datum {
3442 matches ! ( self , Datum :: Bytes ( _) )
3543 }
3644
37- pub fn cast_float ( self ) -> Self {
38- match self {
39- Datum :: Int ( v) => Datum :: Float ( F64 :: from ( v as f64 ) ) ,
40- Datum :: UInt ( v) => Datum :: Float ( F64 :: from ( v as f64 ) ) ,
41- _ => self ,
42- }
43- }
44-
4545 pub fn as_double ( & self ) -> Result < f64 , ErrorCode > {
4646 match self {
4747 Datum :: Bool ( v) => Ok ( * v as u8 as f64 ) ,
@@ -122,6 +122,104 @@ impl Datum {
122122 matches ! ( self , Datum :: Int ( _) | Datum :: UInt ( _) | Datum :: Float ( _) )
123123 }
124124
125+ pub fn kind ( & self ) -> Option < DatumKind > {
126+ match self {
127+ Datum :: Int ( _) => Some ( DatumKind :: Int ) ,
128+ Datum :: UInt ( _) => Some ( DatumKind :: UInt ) ,
129+ Datum :: Float ( _) => Some ( DatumKind :: Float ) ,
130+ Datum :: Bytes ( _) => Some ( DatumKind :: Bytes ) ,
131+ Datum :: Bool ( _) => None ,
132+ }
133+ }
134+
135+ pub fn normalize_to_kind ( & self , kind : DatumKind ) -> Option < Datum > {
136+ match kind {
137+ DatumKind :: Int => self . as_i64 ( ) . map ( Datum :: Int ) ,
138+ DatumKind :: UInt => self . as_u64 ( ) . map ( Datum :: UInt ) ,
139+ DatumKind :: Float => self . as_double ( ) . ok ( ) . map ( F64 :: from) . map ( Datum :: Float ) ,
140+ DatumKind :: Bytes => match self {
141+ Datum :: Bytes ( value) => Some ( Datum :: Bytes ( value. clone ( ) ) ) ,
142+ _ => None ,
143+ } ,
144+ }
145+ }
146+
147+ pub fn lower_bound_to_kind ( & self , kind : DatumKind ) -> Option < Datum > {
148+ match kind {
149+ DatumKind :: Int => self . lower_bound_as_i64 ( ) . map ( Datum :: Int ) ,
150+ DatumKind :: UInt => self . lower_bound_as_u64 ( ) . map ( Datum :: UInt ) ,
151+ _ => self . normalize_to_kind ( kind) ,
152+ }
153+ }
154+
155+ pub fn upper_bound_to_kind ( & self , kind : DatumKind ) -> Option < Datum > {
156+ match kind {
157+ DatumKind :: Int => self . upper_bound_as_i64 ( ) . map ( Datum :: Int ) ,
158+ DatumKind :: UInt => self . upper_bound_as_u64 ( ) . map ( Datum :: UInt ) ,
159+ _ => self . normalize_to_kind ( kind) ,
160+ }
161+ }
162+
163+ pub fn as_i64 ( & self ) -> Option < i64 > {
164+ match self {
165+ Datum :: Int ( value) => Some ( * value) ,
166+ Datum :: UInt ( value) => i64:: try_from ( * value) . ok ( ) ,
167+ Datum :: Float ( value) => {
168+ let value = value. into_inner ( ) ;
169+ ( value. is_finite ( )
170+ && value. fract ( ) == 0.0
171+ && value >= i64:: MIN as f64
172+ && value <= i64:: MAX as f64 )
173+ . then_some ( value as i64 )
174+ }
175+ _ => None ,
176+ }
177+ }
178+
179+ pub fn as_u64 ( & self ) -> Option < u64 > {
180+ match self {
181+ Datum :: UInt ( value) => Some ( * value) ,
182+ Datum :: Int ( value) => u64:: try_from ( * value) . ok ( ) ,
183+ Datum :: Float ( value) => {
184+ let value = value. into_inner ( ) ;
185+ ( value. is_finite ( )
186+ && value. fract ( ) == 0.0
187+ && value >= 0.0
188+ && value <= u64:: MAX as f64 )
189+ . then_some ( value as u64 )
190+ }
191+ _ => None ,
192+ }
193+ }
194+
195+ fn lower_bound_as_i64 ( & self ) -> Option < i64 > {
196+ match self {
197+ Datum :: Float ( value) => float_to_i64_bound ( value. into_inner ( ) , f64:: ceil) ,
198+ _ => self . as_i64 ( ) ,
199+ }
200+ }
201+
202+ fn upper_bound_as_i64 ( & self ) -> Option < i64 > {
203+ match self {
204+ Datum :: Float ( value) => float_to_i64_bound ( value. into_inner ( ) , f64:: floor) ,
205+ _ => self . as_i64 ( ) ,
206+ }
207+ }
208+
209+ fn lower_bound_as_u64 ( & self ) -> Option < u64 > {
210+ match self {
211+ Datum :: Float ( value) => float_to_u64_bound ( value. into_inner ( ) , f64:: ceil) ,
212+ _ => self . as_u64 ( ) ,
213+ }
214+ }
215+
216+ fn upper_bound_as_u64 ( & self ) -> Option < u64 > {
217+ match self {
218+ Datum :: Float ( value) => float_to_u64_bound ( value. into_inner ( ) , f64:: floor) ,
219+ _ => self . as_u64 ( ) ,
220+ }
221+ }
222+
125223 pub fn type_name ( & self ) -> & ' static str {
126224 match self {
127225 Datum :: Bool ( _) => "Boolean" ,
@@ -159,3 +257,14 @@ impl Datum {
159257 }
160258 }
161259}
260+
261+ fn float_to_i64_bound ( value : f64 , round : fn ( f64 ) -> f64 ) -> Option < i64 > {
262+ let value = round ( value) ;
263+ ( value. is_finite ( ) && value >= i64:: MIN as f64 && value <= i64:: MAX as f64 )
264+ . then_some ( value as i64 )
265+ }
266+
267+ fn float_to_u64_bound ( value : f64 , round : fn ( f64 ) -> f64 ) -> Option < u64 > {
268+ let value = round ( value) ;
269+ ( value. is_finite ( ) && value >= 0.0 && value <= u64:: MAX as f64 ) . then_some ( value as u64 )
270+ }
0 commit comments