1717
1818//! Defines scalars used to construct groups, ex. in GROUP BY clauses.
1919
20+ use ordered_float:: OrderedFloat ;
2021use std:: convert:: { From , TryFrom } ;
2122
2223use crate :: error:: { DataFusionError , Result } ;
2324use crate :: scalar:: ScalarValue ;
2425
25- /// Enumeration of types that can be used in a GROUP BY expression (all primitives except
26- /// for floating point numerics)
26+ /// Enumeration of types that can be used in a GROUP BY expression
2727#[ derive( Debug , PartialEq , Eq , Hash , Clone ) ]
2828pub ( crate ) enum GroupByScalar {
29+ Float32 ( OrderedFloat < f32 > ) ,
30+ Float64 ( OrderedFloat < f64 > ) ,
2931 UInt8 ( u8 ) ,
3032 UInt16 ( u16 ) ,
3133 UInt32 ( u32 ) ,
@@ -44,6 +46,12 @@ impl TryFrom<&ScalarValue> for GroupByScalar {
4446
4547 fn try_from ( scalar_value : & ScalarValue ) -> Result < Self > {
4648 Ok ( match scalar_value {
49+ ScalarValue :: Float32 ( Some ( v) ) => {
50+ GroupByScalar :: Float32 ( OrderedFloat :: from ( * v) )
51+ }
52+ ScalarValue :: Float64 ( Some ( v) ) => {
53+ GroupByScalar :: Float64 ( OrderedFloat :: from ( * v) )
54+ }
4755 ScalarValue :: Int8 ( Some ( v) ) => GroupByScalar :: Int8 ( * v) ,
4856 ScalarValue :: Int16 ( Some ( v) ) => GroupByScalar :: Int16 ( * v) ,
4957 ScalarValue :: Int32 ( Some ( v) ) => GroupByScalar :: Int32 ( * v) ,
@@ -53,7 +61,9 @@ impl TryFrom<&ScalarValue> for GroupByScalar {
5361 ScalarValue :: UInt32 ( Some ( v) ) => GroupByScalar :: UInt32 ( * v) ,
5462 ScalarValue :: UInt64 ( Some ( v) ) => GroupByScalar :: UInt64 ( * v) ,
5563 ScalarValue :: Utf8 ( Some ( v) ) => GroupByScalar :: Utf8 ( Box :: new ( v. clone ( ) ) ) ,
56- ScalarValue :: Int8 ( None )
64+ ScalarValue :: Float32 ( None )
65+ | ScalarValue :: Float64 ( None )
66+ | ScalarValue :: Int8 ( None )
5767 | ScalarValue :: Int16 ( None )
5868 | ScalarValue :: Int32 ( None )
5969 | ScalarValue :: Int64 ( None )
@@ -80,6 +90,8 @@ impl TryFrom<&ScalarValue> for GroupByScalar {
8090impl From < & GroupByScalar > for ScalarValue {
8191 fn from ( group_by_scalar : & GroupByScalar ) -> Self {
8292 match group_by_scalar {
93+ GroupByScalar :: Float32 ( v) => ScalarValue :: Float32 ( Some ( ( * v) . into ( ) ) ) ,
94+ GroupByScalar :: Float64 ( v) => ScalarValue :: Float64 ( Some ( ( * v) . into ( ) ) ) ,
8395 GroupByScalar :: Int8 ( v) => ScalarValue :: Int8 ( Some ( * v) ) ,
8496 GroupByScalar :: Int16 ( v) => ScalarValue :: Int16 ( Some ( * v) ) ,
8597 GroupByScalar :: Int32 ( v) => ScalarValue :: Int32 ( Some ( * v) ) ,
@@ -101,6 +113,48 @@ mod tests {
101113
102114 use crate :: error:: { DataFusionError , Result } ;
103115
116+ macro_rules! scalar_eq_test {
117+ ( $TYPE: expr, $VALUE: expr) => { {
118+ let scalar_value = $TYPE( $VALUE) ;
119+ let a = GroupByScalar :: try_from( & scalar_value) . unwrap( ) ;
120+
121+ let scalar_value = $TYPE( $VALUE) ;
122+ let b = GroupByScalar :: try_from( & scalar_value) . unwrap( ) ;
123+
124+ assert_eq!( a, b) ;
125+ } } ;
126+ }
127+
128+ #[ test]
129+ fn test_scalar_ne_non_std ( ) -> Result < ( ) > {
130+ // Test only Scalars with non native Eq, Hash
131+ scalar_eq_test ! ( ScalarValue :: Float32 , Some ( 1.0 ) ) ;
132+ scalar_eq_test ! ( ScalarValue :: Float64 , Some ( 1.0 ) ) ;
133+
134+ Ok ( ( ) )
135+ }
136+
137+ macro_rules! scalar_ne_test {
138+ ( $TYPE: expr, $LVALUE: expr, $RVALUE: expr) => { {
139+ let scalar_value = $TYPE( $LVALUE) ;
140+ let a = GroupByScalar :: try_from( & scalar_value) . unwrap( ) ;
141+
142+ let scalar_value = $TYPE( $RVALUE) ;
143+ let b = GroupByScalar :: try_from( & scalar_value) . unwrap( ) ;
144+
145+ assert_ne!( a, b) ;
146+ } } ;
147+ }
148+
149+ #[ test]
150+ fn test_scalar_eq_non_std ( ) -> Result < ( ) > {
151+ // Test only Scalars with non native Eq, Hash
152+ scalar_ne_test ! ( ScalarValue :: Float32 , Some ( 1.0 ) , Some ( 2.0 ) ) ;
153+ scalar_ne_test ! ( ScalarValue :: Float64 , Some ( 1.0 ) , Some ( 2.0 ) ) ;
154+
155+ Ok ( ( ) )
156+ }
157+
104158 #[ test]
105159 fn from_scalar_holding_none ( ) -> Result < ( ) > {
106160 let scalar_value = ScalarValue :: Int8 ( None ) ;
@@ -120,14 +174,14 @@ mod tests {
120174 #[ test]
121175 fn from_scalar_unsupported ( ) -> Result < ( ) > {
122176 // Use any ScalarValue type not supported by GroupByScalar.
123- let scalar_value = ScalarValue :: Float32 ( Some ( 1.1 ) ) ;
177+ let scalar_value = ScalarValue :: LargeUtf8 ( Some ( " 1.1" . to_string ( ) ) ) ;
124178 let result = GroupByScalar :: try_from ( & scalar_value) ;
125179
126180 match result {
127181 Err ( DataFusionError :: Internal ( error_message) ) => assert_eq ! (
128182 error_message,
129183 String :: from(
130- "Cannot convert a ScalarValue with associated DataType Float32 "
184+ "Cannot convert a ScalarValue with associated DataType LargeUtf8 "
131185 )
132186 ) ,
133187 _ => panic ! ( "Unexpected result" ) ,
0 commit comments