@@ -25,7 +25,9 @@ use std::cmp::Ordering;
25
25
26
26
use arrow:: datatypes:: {
27
27
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 ,
29
31
} ;
30
32
use arrow:: temporal_conversions:: { MICROSECONDS , MILLISECONDS , NANOSECONDS } ;
31
33
use datafusion_common:: ScalarValue ;
@@ -69,6 +71,8 @@ fn is_supported_numeric_type(data_type: &DataType) -> bool {
69
71
| DataType :: Int16
70
72
| DataType :: Int32
71
73
| DataType :: Int64
74
+ | DataType :: Decimal32 ( _, _)
75
+ | DataType :: Decimal64 ( _, _)
72
76
| DataType :: Decimal128 ( _, _)
73
77
| DataType :: Timestamp ( _, _)
74
78
)
@@ -114,6 +118,8 @@ fn try_cast_numeric_literal(
114
118
| DataType :: Int32
115
119
| DataType :: Int64 => 1_i128 ,
116
120
DataType :: Timestamp ( _, _) => 1_i128 ,
121
+ DataType :: Decimal32 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
122
+ DataType :: Decimal64 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
117
123
DataType :: Decimal128 ( _, scale) => 10_i128 . pow ( * scale as u32 ) ,
118
124
_ => return None ,
119
125
} ;
@@ -127,6 +133,20 @@ fn try_cast_numeric_literal(
127
133
DataType :: Int32 => ( i32:: MIN as i128 , i32:: MAX as i128 ) ,
128
134
DataType :: Int64 => ( i64:: MIN as i128 , i64:: MAX as i128 ) ,
129
135
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
+ ) ,
130
150
DataType :: Decimal128 ( precision, _) => (
131
151
// Different precision for decimal128 can store different range of value.
132
152
// For example, the precision is 3, the max of value is `999` and the min
@@ -149,6 +169,46 @@ fn try_cast_numeric_literal(
149
169
ScalarValue :: TimestampMillisecond ( Some ( v) , _) => ( * v as i128 ) . checked_mul ( mul) ,
150
170
ScalarValue :: TimestampMicrosecond ( Some ( v) , _) => ( * v as i128 ) . checked_mul ( mul) ,
151
171
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
+ }
152
212
ScalarValue :: Decimal128 ( Some ( v) , _, scale) => {
153
213
let lit_scale_mul = 10_i128 . pow ( * scale as u32 ) ;
154
214
if mul >= lit_scale_mul {
@@ -218,6 +278,12 @@ fn try_cast_numeric_literal(
218
278
) ;
219
279
ScalarValue :: TimestampNanosecond ( value, tz. clone ( ) )
220
280
}
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
+ }
221
287
DataType :: Decimal128 ( p, s) => {
222
288
ScalarValue :: Decimal128 ( Some ( value) , * p, * s)
223
289
}
0 commit comments