@@ -777,29 +777,19 @@ pub fn binary_numeric_coercion(
777777 ( _, Float32 ) | ( Float32 , _) => Some ( Float32 ) ,
778778 // The following match arms encode the following logic: Given the two
779779 // integral types, we choose the narrowest possible integral type that
780- // accommodates all values of both types. Note that some information
781- // loss is inevitable when we have a signed type and a `UInt64`, in
782- // which case we use `Int64`;i.e. the widest signed integral type.
783-
784- // TODO: For i64 and u64, we can use decimal or float64
785- // Postgres has no unsigned type :(
786- // DuckDB v.0.10.0 has double (double precision floating-point number (8 bytes))
787- // for largest signed (signed sixteen-byte integer) and unsigned integer (unsigned sixteen-byte integer)
780+ // accommodates all values of both types. Note that to avoid information
781+ // loss when combining UInt64 with signed integers we use Decimal128(20, 0).
782+ ( UInt64 , Int64 | Int32 | Int16 | Int8 )
783+ | ( Int64 | Int32 | Int16 | Int8 , UInt64 ) => Some ( Decimal128 ( 20 , 0 ) ) ,
784+ ( UInt64 , _) | ( _, UInt64 ) => Some ( UInt64 ) ,
788785 ( Int64 , _)
789786 | ( _, Int64 )
790- | ( UInt64 , Int8 )
791- | ( Int8 , UInt64 )
792- | ( UInt64 , Int16 )
793- | ( Int16 , UInt64 )
794- | ( UInt64 , Int32 )
795- | ( Int32 , UInt64 )
796787 | ( UInt32 , Int8 )
797788 | ( Int8 , UInt32 )
798789 | ( UInt32 , Int16 )
799790 | ( Int16 , UInt32 )
800791 | ( UInt32 , Int32 )
801792 | ( Int32 , UInt32 ) => Some ( Int64 ) ,
802- ( UInt64 , _) | ( _, UInt64 ) => Some ( UInt64 ) ,
803793 ( Int32 , _)
804794 | ( _, Int32 )
805795 | ( UInt16 , Int16 )
@@ -928,16 +918,16 @@ pub fn get_wider_type(lhs: &DataType, rhs: &DataType) -> Result<DataType> {
928918}
929919
930920/// Convert the numeric data type to the decimal data type.
931- /// Now, we just support the signed integer type and floating-point type.
921+ /// We support signed and unsigned integer types and floating-point type.
932922fn coerce_numeric_type_to_decimal ( numeric_type : & DataType ) -> Option < DataType > {
933923 use arrow:: datatypes:: DataType :: * ;
934924 // This conversion rule is from spark
935925 // https://github.com/apache/spark/blob/1c81ad20296d34f137238dadd67cc6ae405944eb/sql/catalyst/src/main/scala/org/apache/spark/sql/types/DecimalType.scala#L127
936926 match numeric_type {
937- Int8 => Some ( Decimal128 ( 3 , 0 ) ) ,
938- Int16 => Some ( Decimal128 ( 5 , 0 ) ) ,
939- Int32 => Some ( Decimal128 ( 10 , 0 ) ) ,
940- Int64 => Some ( Decimal128 ( 20 , 0 ) ) ,
927+ Int8 | UInt8 => Some ( Decimal128 ( 3 , 0 ) ) ,
928+ Int16 | UInt16 => Some ( Decimal128 ( 5 , 0 ) ) ,
929+ Int32 | UInt32 => Some ( Decimal128 ( 10 , 0 ) ) ,
930+ Int64 | UInt64 => Some ( Decimal128 ( 20 , 0 ) ) ,
941931 // TODO if we convert the floating-point data to the decimal type, it maybe overflow.
942932 Float32 => Some ( Decimal128 ( 14 , 7 ) ) ,
943933 Float64 => Some ( Decimal128 ( 30 , 15 ) ) ,
@@ -946,16 +936,16 @@ fn coerce_numeric_type_to_decimal(numeric_type: &DataType) -> Option<DataType> {
946936}
947937
948938/// Convert the numeric data type to the decimal data type.
949- /// Now, we just support the signed integer type and floating-point type.
939+ /// We support signed and unsigned integer types and floating-point type.
950940fn coerce_numeric_type_to_decimal256 ( numeric_type : & DataType ) -> Option < DataType > {
951941 use arrow:: datatypes:: DataType :: * ;
952942 // This conversion rule is from spark
953943 // https://github.com/apache/spark/blob/1c81ad20296d34f137238dadd67cc6ae405944eb/sql/catalyst/src/main/scala/org/apache/spark/sql/types/DecimalType.scala#L127
954944 match numeric_type {
955- Int8 => Some ( Decimal256 ( 3 , 0 ) ) ,
956- Int16 => Some ( Decimal256 ( 5 , 0 ) ) ,
957- Int32 => Some ( Decimal256 ( 10 , 0 ) ) ,
958- Int64 => Some ( Decimal256 ( 20 , 0 ) ) ,
945+ Int8 | UInt8 => Some ( Decimal256 ( 3 , 0 ) ) ,
946+ Int16 | UInt16 => Some ( Decimal256 ( 5 , 0 ) ) ,
947+ Int32 | UInt32 => Some ( Decimal256 ( 10 , 0 ) ) ,
948+ Int64 | UInt64 => Some ( Decimal256 ( 20 , 0 ) ) ,
959949 // TODO if we convert the floating-point data to the decimal type, it maybe overflow.
960950 Float32 => Some ( Decimal256 ( 14 , 7 ) ) ,
961951 Float64 => Some ( Decimal256 ( 30 , 15 ) ) ,
@@ -1994,6 +1984,18 @@ mod tests {
19941984 Operator :: Gt ,
19951985 DataType :: UInt32
19961986 ) ;
1987+ test_coercion_binary_rule ! (
1988+ DataType :: UInt64 ,
1989+ DataType :: UInt8 ,
1990+ Operator :: Eq ,
1991+ DataType :: UInt64
1992+ ) ;
1993+ test_coercion_binary_rule ! (
1994+ DataType :: UInt64 ,
1995+ DataType :: Int64 ,
1996+ Operator :: Eq ,
1997+ DataType :: Decimal128 ( 20 , 0 )
1998+ ) ;
19971999 // numeric/decimal
19982000 test_coercion_binary_rule ! (
19992001 DataType :: Int64 ,
@@ -2025,6 +2027,12 @@ mod tests {
20252027 Operator :: GtEq ,
20262028 DataType :: Decimal128 ( 15 , 3 )
20272029 ) ;
2030+ test_coercion_binary_rule ! (
2031+ DataType :: UInt64 ,
2032+ DataType :: Decimal128 ( 20 , 0 ) ,
2033+ Operator :: Eq ,
2034+ DataType :: Decimal128 ( 20 , 0 )
2035+ ) ;
20282036
20292037 // Binary
20302038 test_coercion_binary_rule ! (
0 commit comments