@@ -25,7 +25,9 @@ use std::cmp::Ordering;
2525
2626use arrow:: datatypes:: {
2727 DataType , TimeUnit , MAX_DECIMAL128_FOR_EACH_PRECISION ,
28- MIN_DECIMAL128_FOR_EACH_PRECISION ,
28+ MAX_DECIMAL32_FOR_EACH_PRECISION , MAX_DECIMAL64_FOR_EACH_PRECISION ,
29+ MIN_DECIMAL128_FOR_EACH_PRECISION , MIN_DECIMAL32_FOR_EACH_PRECISION ,
30+ MIN_DECIMAL64_FOR_EACH_PRECISION ,
2931} ;
3032use arrow:: temporal_conversions:: { MICROSECONDS , MILLISECONDS , NANOSECONDS } ;
3133use datafusion_common:: ScalarValue ;
@@ -69,6 +71,8 @@ fn is_supported_numeric_type(data_type: &DataType) -> bool {
6971 | DataType :: Int16
7072 | DataType :: Int32
7173 | DataType :: Int64
74+ | DataType :: Decimal32 ( _, _)
75+ | DataType :: Decimal64 ( _, _)
7276 | DataType :: Decimal128 ( _, _)
7377 | DataType :: Timestamp ( _, _)
7478 )
@@ -114,6 +118,8 @@ fn try_cast_numeric_literal(
114118 | DataType :: Int32
115119 | DataType :: Int64 => 1_i128 ,
116120 DataType :: Timestamp ( _, _) => 1_i128 ,
121+ DataType :: Decimal32 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
122+ DataType :: Decimal64 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
117123 DataType :: Decimal128 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
118124 _ => return None ,
119125 } ;
@@ -127,6 +133,20 @@ fn try_cast_numeric_literal(
127133 DataType :: Int32 => ( i32:: MIN as i128 , i32:: MAX as i128 ) ,
128134 DataType :: Int64 => ( i64:: MIN as i128 , i64:: MAX as i128 ) ,
129135 DataType :: Timestamp ( _, _) => ( i64:: MIN as i128 , i64:: MAX as i128 ) ,
136+ DataType :: Decimal32 ( precision, _) => (
137+ // Different precision for decimal32 can store different range of value.
138+ // For example, the precision is 3, the max of value is `999` and the min
139+ // value is `-999`
140+ MIN_DECIMAL32_FOR_EACH_PRECISION [ * precision as usize ] as i128 ,
141+ MAX_DECIMAL32_FOR_EACH_PRECISION [ * precision as usize ] as i128 ,
142+ ) ,
143+ DataType :: Decimal64 ( precision, _) => (
144+ // Different precision for decimal64 can store different range of value.
145+ // For example, the precision is 3, the max of value is `999` and the min
146+ // value is `-999`
147+ MIN_DECIMAL64_FOR_EACH_PRECISION [ * precision as usize ] as i128 ,
148+ MAX_DECIMAL64_FOR_EACH_PRECISION [ * precision as usize ] as i128 ,
149+ ) ,
130150 DataType :: Decimal128 ( precision, _) => (
131151 // Different precision for decimal128 can store different range of value.
132152 // For example, the precision is 3, the max of value is `999` and the min
@@ -149,6 +169,46 @@ fn try_cast_numeric_literal(
149169 ScalarValue :: TimestampMillisecond ( Some ( v) , _) => ( * v as i128 ) . checked_mul ( mul) ,
150170 ScalarValue :: TimestampMicrosecond ( Some ( v) , _) => ( * v as i128 ) . checked_mul ( mul) ,
151171 ScalarValue :: TimestampNanosecond ( Some ( v) , _) => ( * v as i128 ) . checked_mul ( mul) ,
172+ ScalarValue :: Decimal32 ( Some ( v) , _, scale) => {
173+ let v = * v as i128 ;
174+ let lit_scale_mul = 10_i128 . pow ( * scale as u32 ) ;
175+ if mul >= lit_scale_mul {
176+ // Example:
177+ // lit is decimal(123,3,2)
178+ // target type is decimal(5,3)
179+ // the lit can be converted to the decimal(1230,5,3)
180+ v. checked_mul ( mul / lit_scale_mul)
181+ } else if v % ( lit_scale_mul / mul) == 0 {
182+ // Example:
183+ // lit is decimal(123000,10,3)
184+ // target type is int32: the lit can be converted to INT32(123)
185+ // target type is decimal(10,2): the lit can be converted to decimal(12300,10,2)
186+ Some ( v / ( lit_scale_mul / mul) )
187+ } else {
188+ // can't convert the lit decimal to the target data type
189+ None
190+ }
191+ }
192+ ScalarValue :: Decimal64 ( Some ( v) , _, scale) => {
193+ let v = * v as i128 ;
194+ let lit_scale_mul = 10_i128 . pow ( * scale as u32 ) ;
195+ if mul >= lit_scale_mul {
196+ // Example:
197+ // lit is decimal(123,3,2)
198+ // target type is decimal(5,3)
199+ // the lit can be converted to the decimal(1230,5,3)
200+ v. checked_mul ( mul / lit_scale_mul)
201+ } else if v % ( lit_scale_mul / mul) == 0 {
202+ // Example:
203+ // lit is decimal(123000,10,3)
204+ // target type is int32: the lit can be converted to INT32(123)
205+ // target type is decimal(10,2): the lit can be converted to decimal(12300,10,2)
206+ Some ( v / ( lit_scale_mul / mul) )
207+ } else {
208+ // can't convert the lit decimal to the target data type
209+ None
210+ }
211+ }
152212 ScalarValue :: Decimal128 ( Some ( v) , _, scale) => {
153213 let lit_scale_mul = 10_i128 . pow ( * scale as u32 ) ;
154214 if mul >= lit_scale_mul {
@@ -218,6 +278,12 @@ fn try_cast_numeric_literal(
218278 ) ;
219279 ScalarValue :: TimestampNanosecond ( value, tz. clone ( ) )
220280 }
281+ DataType :: Decimal32 ( p, s) => {
282+ ScalarValue :: Decimal32 ( Some ( value as i32 ) , * p, * s)
283+ }
284+ DataType :: Decimal64 ( p, s) => {
285+ ScalarValue :: Decimal64 ( Some ( value as i64 ) , * p, * s)
286+ }
221287 DataType :: Decimal128 ( p, s) => {
222288 ScalarValue :: Decimal128 ( Some ( value) , * p, * s)
223289 }
0 commit comments