lance_datafusion/
expr.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4//! Utilities for working with datafusion expressions
5
6use std::sync::Arc;
7
8use arrow::compute::cast;
9use arrow_array::{cast::AsArray, ArrayRef};
10use arrow_schema::{DataType, TimeUnit};
11use datafusion_common::ScalarValue;
12
13const MS_PER_DAY: i64 = 86400000;
14
15// This is slightly tedious but when we convert expressions from SQL strings to logical
16// datafusion expressions there is no type coercion that happens.  In other words "x = 7"
17// will always yield "x = 7_u64" regardless of the type of the column "x".  As a result, we
18// need to do that literal coercion ourselves.
19pub fn safe_coerce_scalar(value: &ScalarValue, ty: &DataType) -> Option<ScalarValue> {
20    match value {
21        ScalarValue::Int8(val) => match ty {
22            DataType::Int8 => Some(value.clone()),
23            DataType::Int16 => val.map(|v| ScalarValue::Int16(Some(i16::from(v)))),
24            DataType::Int32 => val.map(|v| ScalarValue::Int32(Some(i32::from(v)))),
25            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(i64::from(v)))),
26            DataType::UInt8 => {
27                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
28            }
29            DataType::UInt16 => {
30                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
31            }
32            DataType::UInt32 => {
33                val.and_then(|v| u32::try_from(v).map(|v| ScalarValue::UInt32(Some(v))).ok())
34            }
35            DataType::UInt64 => {
36                val.and_then(|v| u64::try_from(v).map(|v| ScalarValue::UInt64(Some(v))).ok())
37            }
38            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(f32::from(v)))),
39            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(f64::from(v)))),
40            _ => None,
41        },
42        ScalarValue::Int16(val) => match ty {
43            DataType::Int8 => {
44                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
45            }
46            DataType::Int16 => Some(value.clone()),
47            DataType::Int32 => val.map(|v| ScalarValue::Int32(Some(i32::from(v)))),
48            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(i64::from(v)))),
49            DataType::UInt8 => {
50                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
51            }
52            DataType::UInt16 => {
53                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
54            }
55            DataType::UInt32 => {
56                val.and_then(|v| u32::try_from(v).map(|v| ScalarValue::UInt32(Some(v))).ok())
57            }
58            DataType::UInt64 => {
59                val.and_then(|v| u64::try_from(v).map(|v| ScalarValue::UInt64(Some(v))).ok())
60            }
61            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(f32::from(v)))),
62            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(f64::from(v)))),
63            _ => None,
64        },
65        ScalarValue::Int32(val) => match ty {
66            DataType::Int8 => {
67                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
68            }
69            DataType::Int16 => {
70                val.and_then(|v| i16::try_from(v).map(|v| ScalarValue::Int16(Some(v))).ok())
71            }
72            DataType::Int32 => Some(value.clone()),
73            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(i64::from(v)))),
74            DataType::UInt8 => {
75                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
76            }
77            DataType::UInt16 => {
78                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
79            }
80            DataType::UInt32 => {
81                val.and_then(|v| u32::try_from(v).map(|v| ScalarValue::UInt32(Some(v))).ok())
82            }
83            DataType::UInt64 => {
84                val.and_then(|v| u64::try_from(v).map(|v| ScalarValue::UInt64(Some(v))).ok())
85            }
86            // These conversions are inherently lossy as the full range of i32 cannot
87            // be represented in f32.  However, there is no f32::TryFrom(i32) and its not
88            // clear users would want that anyways
89            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(v as f32))),
90            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(v as f64))),
91            _ => None,
92        },
93        ScalarValue::Int64(val) => match ty {
94            DataType::Int8 => {
95                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
96            }
97            DataType::Int16 => {
98                val.and_then(|v| i16::try_from(v).map(|v| ScalarValue::Int16(Some(v))).ok())
99            }
100            DataType::Int32 => {
101                val.and_then(|v| i32::try_from(v).map(|v| ScalarValue::Int32(Some(v))).ok())
102            }
103            DataType::Int64 => Some(value.clone()),
104            DataType::UInt8 => {
105                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
106            }
107            DataType::UInt16 => {
108                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
109            }
110            DataType::UInt32 => {
111                val.and_then(|v| u32::try_from(v).map(|v| ScalarValue::UInt32(Some(v))).ok())
112            }
113            DataType::UInt64 => {
114                val.and_then(|v| u64::try_from(v).map(|v| ScalarValue::UInt64(Some(v))).ok())
115            }
116            // See above warning about lossy float conversion
117            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(v as f32))),
118            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(v as f64))),
119            _ => None,
120        },
121        ScalarValue::UInt8(val) => match ty {
122            DataType::Int8 => {
123                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
124            }
125            DataType::Int16 => val.map(|v| ScalarValue::Int16(Some(v.into()))),
126            DataType::Int32 => val.map(|v| ScalarValue::Int32(Some(v.into()))),
127            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(v.into()))),
128            DataType::UInt8 => Some(value.clone()),
129            DataType::UInt16 => val.map(|v| ScalarValue::UInt16(Some(u16::from(v)))),
130            DataType::UInt32 => val.map(|v| ScalarValue::UInt32(Some(u32::from(v)))),
131            DataType::UInt64 => val.map(|v| ScalarValue::UInt64(Some(u64::from(v)))),
132            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(f32::from(v)))),
133            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(f64::from(v)))),
134            _ => None,
135        },
136        ScalarValue::UInt16(val) => match ty {
137            DataType::Int8 => {
138                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
139            }
140            DataType::Int16 => {
141                val.and_then(|v| i16::try_from(v).map(|v| ScalarValue::Int16(Some(v))).ok())
142            }
143            DataType::Int32 => val.map(|v| ScalarValue::Int32(Some(v.into()))),
144            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(v.into()))),
145            DataType::UInt8 => {
146                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
147            }
148            DataType::UInt16 => Some(value.clone()),
149            DataType::UInt32 => val.map(|v| ScalarValue::UInt32(Some(u32::from(v)))),
150            DataType::UInt64 => val.map(|v| ScalarValue::UInt64(Some(u64::from(v)))),
151            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(f32::from(v)))),
152            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(f64::from(v)))),
153            _ => None,
154        },
155        ScalarValue::UInt32(val) => match ty {
156            DataType::Int8 => {
157                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
158            }
159            DataType::Int16 => {
160                val.and_then(|v| i16::try_from(v).map(|v| ScalarValue::Int16(Some(v))).ok())
161            }
162            DataType::Int32 => {
163                val.and_then(|v| i32::try_from(v).map(|v| ScalarValue::Int32(Some(v))).ok())
164            }
165            DataType::Int64 => val.map(|v| ScalarValue::Int64(Some(v.into()))),
166            DataType::UInt8 => {
167                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
168            }
169            DataType::UInt16 => {
170                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
171            }
172            DataType::UInt32 => Some(value.clone()),
173            DataType::UInt64 => val.map(|v| ScalarValue::UInt64(Some(u64::from(v)))),
174            // See above warning about lossy float conversion
175            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(v as f32))),
176            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(v as f64))),
177            _ => None,
178        },
179        ScalarValue::UInt64(val) => match ty {
180            DataType::Int8 => {
181                val.and_then(|v| i8::try_from(v).map(|v| ScalarValue::Int8(Some(v))).ok())
182            }
183            DataType::Int16 => {
184                val.and_then(|v| i16::try_from(v).map(|v| ScalarValue::Int16(Some(v))).ok())
185            }
186            DataType::Int32 => {
187                val.and_then(|v| i32::try_from(v).map(|v| ScalarValue::Int32(Some(v))).ok())
188            }
189            DataType::Int64 => {
190                val.and_then(|v| i64::try_from(v).map(|v| ScalarValue::Int64(Some(v))).ok())
191            }
192            DataType::UInt8 => {
193                val.and_then(|v| u8::try_from(v).map(|v| ScalarValue::UInt8(Some(v))).ok())
194            }
195            DataType::UInt16 => {
196                val.and_then(|v| u16::try_from(v).map(|v| ScalarValue::UInt16(Some(v))).ok())
197            }
198            DataType::UInt32 => {
199                val.and_then(|v| u32::try_from(v).map(|v| ScalarValue::UInt32(Some(v))).ok())
200            }
201            DataType::UInt64 => Some(value.clone()),
202            // See above warning about lossy float conversion
203            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(v as f32))),
204            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(v as f64))),
205            _ => None,
206        },
207        ScalarValue::Float32(val) => match ty {
208            DataType::Float32 => Some(value.clone()),
209            DataType::Float64 => val.map(|v| ScalarValue::Float64(Some(f64::from(v)))),
210            _ => None,
211        },
212        ScalarValue::Float64(val) => match ty {
213            DataType::Float32 => val.map(|v| ScalarValue::Float32(Some(v as f32))),
214            DataType::Float64 => Some(value.clone()),
215            _ => None,
216        },
217        ScalarValue::Utf8(val) => match ty {
218            DataType::Utf8 => Some(value.clone()),
219            DataType::LargeUtf8 => Some(ScalarValue::LargeUtf8(val.clone())),
220            _ => None,
221        },
222        ScalarValue::LargeUtf8(val) => match ty {
223            DataType::Utf8 => Some(ScalarValue::Utf8(val.clone())),
224            DataType::LargeUtf8 => Some(value.clone()),
225            _ => None,
226        },
227        ScalarValue::Boolean(_) => match ty {
228            DataType::Boolean => Some(value.clone()),
229            _ => None,
230        },
231        ScalarValue::Null => Some(value.clone()),
232        ScalarValue::List(values) => {
233            let values = values.clone() as ArrayRef;
234            let new_values = cast(&values, ty).ok()?;
235            match ty {
236                DataType::List(_) => {
237                    Some(ScalarValue::List(Arc::new(new_values.as_list().clone())))
238                }
239                DataType::LargeList(_) => Some(ScalarValue::LargeList(Arc::new(
240                    new_values.as_list().clone(),
241                ))),
242                DataType::FixedSizeList(_, _) => Some(ScalarValue::FixedSizeList(Arc::new(
243                    new_values.as_fixed_size_list().clone(),
244                ))),
245                _ => None,
246            }
247        }
248        ScalarValue::TimestampSecond(seconds, _) => match ty {
249            DataType::Timestamp(TimeUnit::Second, _) => Some(value.clone()),
250            DataType::Timestamp(TimeUnit::Millisecond, tz) => seconds
251                .and_then(|v| v.checked_mul(1000))
252                .map(|val| ScalarValue::TimestampMillisecond(Some(val), tz.clone())),
253            DataType::Timestamp(TimeUnit::Microsecond, tz) => seconds
254                .and_then(|v| v.checked_mul(1000000))
255                .map(|val| ScalarValue::TimestampMicrosecond(Some(val), tz.clone())),
256            DataType::Timestamp(TimeUnit::Nanosecond, tz) => seconds
257                .and_then(|v| v.checked_mul(1000000000))
258                .map(|val| ScalarValue::TimestampNanosecond(Some(val), tz.clone())),
259            _ => None,
260        },
261        ScalarValue::TimestampMillisecond(millis, _) => match ty {
262            DataType::Timestamp(TimeUnit::Second, tz) => {
263                millis.map(|val| ScalarValue::TimestampSecond(Some(val / 1000), tz.clone()))
264            }
265            DataType::Timestamp(TimeUnit::Millisecond, _) => Some(value.clone()),
266            DataType::Timestamp(TimeUnit::Microsecond, tz) => millis
267                .and_then(|v| v.checked_mul(1000))
268                .map(|val| ScalarValue::TimestampMicrosecond(Some(val), tz.clone())),
269            DataType::Timestamp(TimeUnit::Nanosecond, tz) => millis
270                .and_then(|v| v.checked_mul(1000000))
271                .map(|val| ScalarValue::TimestampNanosecond(Some(val), tz.clone())),
272            _ => None,
273        },
274        ScalarValue::TimestampMicrosecond(micros, _) => match ty {
275            DataType::Timestamp(TimeUnit::Second, tz) => {
276                micros.map(|val| ScalarValue::TimestampSecond(Some(val / 1000000), tz.clone()))
277            }
278            DataType::Timestamp(TimeUnit::Millisecond, tz) => {
279                micros.map(|val| ScalarValue::TimestampMillisecond(Some(val / 1000), tz.clone()))
280            }
281            DataType::Timestamp(TimeUnit::Microsecond, _) => Some(value.clone()),
282            DataType::Timestamp(TimeUnit::Nanosecond, tz) => micros
283                .and_then(|v| v.checked_mul(1000))
284                .map(|val| ScalarValue::TimestampNanosecond(Some(val), tz.clone())),
285            _ => None,
286        },
287        ScalarValue::TimestampNanosecond(nanos, _) => {
288            match ty {
289                DataType::Timestamp(TimeUnit::Second, tz) => nanos
290                    .map(|val| ScalarValue::TimestampSecond(Some(val / 1000000000), tz.clone())),
291                DataType::Timestamp(TimeUnit::Millisecond, tz) => nanos
292                    .map(|val| ScalarValue::TimestampMillisecond(Some(val / 1000000), tz.clone())),
293                DataType::Timestamp(TimeUnit::Microsecond, tz) => {
294                    nanos.map(|val| ScalarValue::TimestampMicrosecond(Some(val / 1000), tz.clone()))
295                }
296                DataType::Timestamp(TimeUnit::Nanosecond, _) => Some(value.clone()),
297                _ => None,
298            }
299        }
300        ScalarValue::Date32(ticks) => match ty {
301            DataType::Date32 => Some(value.clone()),
302            DataType::Date64 => Some(ScalarValue::Date64(
303                ticks.map(|v| i64::from(v) * MS_PER_DAY),
304            )),
305            _ => None,
306        },
307        ScalarValue::Date64(ticks) => match ty {
308            DataType::Date32 => Some(ScalarValue::Date32(ticks.map(|v| (v / MS_PER_DAY) as i32))),
309            DataType::Date64 => Some(value.clone()),
310            _ => None,
311        },
312        ScalarValue::Time32Second(seconds) => {
313            match ty {
314                DataType::Time32(TimeUnit::Second) => Some(value.clone()),
315                DataType::Time32(TimeUnit::Millisecond) => {
316                    seconds.map(|val| ScalarValue::Time32Millisecond(Some(val * 1000)))
317                }
318                DataType::Time64(TimeUnit::Microsecond) => seconds
319                    .map(|val| ScalarValue::Time64Microsecond(Some(i64::from(val) * 1000000))),
320                DataType::Time64(TimeUnit::Nanosecond) => seconds
321                    .map(|val| ScalarValue::Time64Nanosecond(Some(i64::from(val) * 1000000000))),
322                _ => None,
323            }
324        }
325        ScalarValue::Time32Millisecond(millis) => match ty {
326            DataType::Time32(TimeUnit::Second) => {
327                millis.map(|val| ScalarValue::Time32Second(Some(val / 1000)))
328            }
329            DataType::Time32(TimeUnit::Millisecond) => Some(value.clone()),
330            DataType::Time64(TimeUnit::Microsecond) => {
331                millis.map(|val| ScalarValue::Time64Microsecond(Some(i64::from(val) * 1000)))
332            }
333            DataType::Time64(TimeUnit::Nanosecond) => {
334                millis.map(|val| ScalarValue::Time64Nanosecond(Some(i64::from(val) * 1000000)))
335            }
336            _ => None,
337        },
338        ScalarValue::Time64Microsecond(micros) => match ty {
339            DataType::Time32(TimeUnit::Second) => {
340                micros.map(|val| ScalarValue::Time32Second(Some((val / 1000000) as i32)))
341            }
342            DataType::Time32(TimeUnit::Millisecond) => {
343                micros.map(|val| ScalarValue::Time32Millisecond(Some((val / 1000) as i32)))
344            }
345            DataType::Time64(TimeUnit::Microsecond) => Some(value.clone()),
346            DataType::Time64(TimeUnit::Nanosecond) => {
347                micros.map(|val| ScalarValue::Time64Nanosecond(Some(val * 1000)))
348            }
349            _ => None,
350        },
351        ScalarValue::Time64Nanosecond(nanos) => match ty {
352            DataType::Time32(TimeUnit::Second) => {
353                nanos.map(|val| ScalarValue::Time32Second(Some((val / 1000000000) as i32)))
354            }
355            DataType::Time32(TimeUnit::Millisecond) => {
356                nanos.map(|val| ScalarValue::Time32Millisecond(Some((val / 1000000) as i32)))
357            }
358            DataType::Time64(TimeUnit::Microsecond) => {
359                nanos.map(|val| ScalarValue::Time64Microsecond(Some(val / 1000)))
360            }
361            DataType::Time64(TimeUnit::Nanosecond) => Some(value.clone()),
362            _ => None,
363        },
364        ScalarValue::LargeList(values) => {
365            let values = values.clone() as ArrayRef;
366            let new_values = cast(&values, ty).ok()?;
367            match ty {
368                DataType::List(_) => {
369                    Some(ScalarValue::List(Arc::new(new_values.as_list().clone())))
370                }
371                DataType::LargeList(_) => Some(ScalarValue::LargeList(Arc::new(
372                    new_values.as_list().clone(),
373                ))),
374                DataType::FixedSizeList(_, _) => Some(ScalarValue::FixedSizeList(Arc::new(
375                    new_values.as_fixed_size_list().clone(),
376                ))),
377                _ => None,
378            }
379        }
380        ScalarValue::FixedSizeList(values) => {
381            let values = values.clone() as ArrayRef;
382            let new_values = cast(&values, ty).ok()?;
383            match ty {
384                DataType::List(_) => {
385                    Some(ScalarValue::List(Arc::new(new_values.as_list().clone())))
386                }
387                DataType::LargeList(_) => Some(ScalarValue::LargeList(Arc::new(
388                    new_values.as_list().clone(),
389                ))),
390                DataType::FixedSizeList(_, _) => Some(ScalarValue::FixedSizeList(Arc::new(
391                    new_values.as_fixed_size_list().clone(),
392                ))),
393                _ => None,
394            }
395        }
396        ScalarValue::FixedSizeBinary(len, value) => match ty {
397            DataType::FixedSizeBinary(len2) => {
398                if len == len2 {
399                    Some(ScalarValue::FixedSizeBinary(*len, value.clone()))
400                } else {
401                    None
402                }
403            }
404            DataType::Binary => Some(ScalarValue::Binary(value.clone())),
405            _ => None,
406        },
407        ScalarValue::Binary(value) => match ty {
408            DataType::Binary => Some(ScalarValue::Binary(value.clone())),
409            DataType::FixedSizeBinary(len) => {
410                if let Some(value) = value {
411                    if value.len() == *len as usize {
412                        Some(ScalarValue::FixedSizeBinary(*len, Some(value.clone())))
413                    } else {
414                        None
415                    }
416                } else {
417                    None
418                }
419            }
420            _ => None,
421        },
422        _ => None,
423    }
424}
425
426#[cfg(test)]
427mod tests {
428    use super::*;
429
430    #[test]
431    fn test_temporal_coerce() {
432        // Conversion from timestamps in one resolution to timestamps in another resolution is allowed
433        // s->s
434        assert_eq!(
435            safe_coerce_scalar(
436                &ScalarValue::TimestampSecond(Some(5), None),
437                &DataType::Timestamp(TimeUnit::Second, None),
438            ),
439            Some(ScalarValue::TimestampSecond(Some(5), None))
440        );
441        // s->ms
442        assert_eq!(
443            safe_coerce_scalar(
444                &ScalarValue::TimestampSecond(Some(5), None),
445                &DataType::Timestamp(TimeUnit::Millisecond, None),
446            ),
447            Some(ScalarValue::TimestampMillisecond(Some(5000), None))
448        );
449        // s->us
450        assert_eq!(
451            safe_coerce_scalar(
452                &ScalarValue::TimestampSecond(Some(5), None),
453                &DataType::Timestamp(TimeUnit::Microsecond, None),
454            ),
455            Some(ScalarValue::TimestampMicrosecond(Some(5000000), None))
456        );
457        // s->ns
458        assert_eq!(
459            safe_coerce_scalar(
460                &ScalarValue::TimestampSecond(Some(5), None),
461                &DataType::Timestamp(TimeUnit::Nanosecond, None),
462            ),
463            Some(ScalarValue::TimestampNanosecond(Some(5000000000), None))
464        );
465        // ms->s
466        assert_eq!(
467            safe_coerce_scalar(
468                &ScalarValue::TimestampMillisecond(Some(5000), None),
469                &DataType::Timestamp(TimeUnit::Second, None),
470            ),
471            Some(ScalarValue::TimestampSecond(Some(5), None))
472        );
473        // ms->ms
474        assert_eq!(
475            safe_coerce_scalar(
476                &ScalarValue::TimestampMillisecond(Some(5000), None),
477                &DataType::Timestamp(TimeUnit::Millisecond, None),
478            ),
479            Some(ScalarValue::TimestampMillisecond(Some(5000), None))
480        );
481        // ms->us
482        assert_eq!(
483            safe_coerce_scalar(
484                &ScalarValue::TimestampMillisecond(Some(5000), None),
485                &DataType::Timestamp(TimeUnit::Microsecond, None),
486            ),
487            Some(ScalarValue::TimestampMicrosecond(Some(5000000), None))
488        );
489        // ms->ns
490        assert_eq!(
491            safe_coerce_scalar(
492                &ScalarValue::TimestampMillisecond(Some(5000), None),
493                &DataType::Timestamp(TimeUnit::Nanosecond, None),
494            ),
495            Some(ScalarValue::TimestampNanosecond(Some(5000000000), None))
496        );
497        // us->s
498        assert_eq!(
499            safe_coerce_scalar(
500                &ScalarValue::TimestampMicrosecond(Some(5000000), None),
501                &DataType::Timestamp(TimeUnit::Second, None),
502            ),
503            Some(ScalarValue::TimestampSecond(Some(5), None))
504        );
505        // us->ms
506        assert_eq!(
507            safe_coerce_scalar(
508                &ScalarValue::TimestampMicrosecond(Some(5000000), None),
509                &DataType::Timestamp(TimeUnit::Millisecond, None),
510            ),
511            Some(ScalarValue::TimestampMillisecond(Some(5000), None))
512        );
513        // us->us
514        assert_eq!(
515            safe_coerce_scalar(
516                &ScalarValue::TimestampMicrosecond(Some(5000000), None),
517                &DataType::Timestamp(TimeUnit::Microsecond, None),
518            ),
519            Some(ScalarValue::TimestampMicrosecond(Some(5000000), None))
520        );
521        // us->ns
522        assert_eq!(
523            safe_coerce_scalar(
524                &ScalarValue::TimestampMicrosecond(Some(5000000), None),
525                &DataType::Timestamp(TimeUnit::Nanosecond, None),
526            ),
527            Some(ScalarValue::TimestampNanosecond(Some(5000000000), None))
528        );
529        // ns->s
530        assert_eq!(
531            safe_coerce_scalar(
532                &ScalarValue::TimestampNanosecond(Some(5000000000), None),
533                &DataType::Timestamp(TimeUnit::Second, None),
534            ),
535            Some(ScalarValue::TimestampSecond(Some(5), None))
536        );
537        // ns->ms
538        assert_eq!(
539            safe_coerce_scalar(
540                &ScalarValue::TimestampNanosecond(Some(5000000000), None),
541                &DataType::Timestamp(TimeUnit::Millisecond, None),
542            ),
543            Some(ScalarValue::TimestampMillisecond(Some(5000), None))
544        );
545        // ns->us
546        assert_eq!(
547            safe_coerce_scalar(
548                &ScalarValue::TimestampNanosecond(Some(5000000000), None),
549                &DataType::Timestamp(TimeUnit::Microsecond, None),
550            ),
551            Some(ScalarValue::TimestampMicrosecond(Some(5000000), None))
552        );
553        // ns->ns
554        assert_eq!(
555            safe_coerce_scalar(
556                &ScalarValue::TimestampNanosecond(Some(5000000000), None),
557                &DataType::Timestamp(TimeUnit::Nanosecond, None),
558            ),
559            Some(ScalarValue::TimestampNanosecond(Some(5000000000), None))
560        );
561        // Precision loss on coercion is allowed (truncation)
562        // ns->s
563        assert_eq!(
564            safe_coerce_scalar(
565                &ScalarValue::TimestampNanosecond(Some(5987654321), None),
566                &DataType::Timestamp(TimeUnit::Second, None),
567            ),
568            Some(ScalarValue::TimestampSecond(Some(5), None))
569        );
570        // Conversions from date-32 to date-64 is allowed
571        assert_eq!(
572            safe_coerce_scalar(&ScalarValue::Date32(Some(5)), &DataType::Date32,),
573            Some(ScalarValue::Date32(Some(5)))
574        );
575        assert_eq!(
576            safe_coerce_scalar(&ScalarValue::Date32(Some(5)), &DataType::Date64,),
577            Some(ScalarValue::Date64(Some(5 * MS_PER_DAY)))
578        );
579        assert_eq!(
580            safe_coerce_scalar(
581                &ScalarValue::Date64(Some(5 * MS_PER_DAY)),
582                &DataType::Date32,
583            ),
584            Some(ScalarValue::Date32(Some(5)))
585        );
586        assert_eq!(
587            safe_coerce_scalar(&ScalarValue::Date64(Some(5)), &DataType::Date64,),
588            Some(ScalarValue::Date64(Some(5)))
589        );
590        // Time-32 to time-64 (and within time-32 and time-64) is allowed
591        assert_eq!(
592            safe_coerce_scalar(
593                &ScalarValue::Time32Second(Some(5)),
594                &DataType::Time32(TimeUnit::Second),
595            ),
596            Some(ScalarValue::Time32Second(Some(5)))
597        );
598        assert_eq!(
599            safe_coerce_scalar(
600                &ScalarValue::Time32Second(Some(5)),
601                &DataType::Time32(TimeUnit::Millisecond),
602            ),
603            Some(ScalarValue::Time32Millisecond(Some(5000)))
604        );
605        assert_eq!(
606            safe_coerce_scalar(
607                &ScalarValue::Time32Second(Some(5)),
608                &DataType::Time64(TimeUnit::Microsecond),
609            ),
610            Some(ScalarValue::Time64Microsecond(Some(5000000)))
611        );
612        assert_eq!(
613            safe_coerce_scalar(
614                &ScalarValue::Time32Second(Some(5)),
615                &DataType::Time64(TimeUnit::Nanosecond),
616            ),
617            Some(ScalarValue::Time64Nanosecond(Some(5000000000)))
618        );
619        assert_eq!(
620            safe_coerce_scalar(
621                &ScalarValue::Time32Millisecond(Some(5000)),
622                &DataType::Time32(TimeUnit::Second),
623            ),
624            Some(ScalarValue::Time32Second(Some(5)))
625        );
626        assert_eq!(
627            safe_coerce_scalar(
628                &ScalarValue::Time32Millisecond(Some(5000)),
629                &DataType::Time32(TimeUnit::Millisecond),
630            ),
631            Some(ScalarValue::Time32Millisecond(Some(5000)))
632        );
633        assert_eq!(
634            safe_coerce_scalar(
635                &ScalarValue::Time32Millisecond(Some(5000)),
636                &DataType::Time64(TimeUnit::Microsecond),
637            ),
638            Some(ScalarValue::Time64Microsecond(Some(5000000)))
639        );
640        assert_eq!(
641            safe_coerce_scalar(
642                &ScalarValue::Time32Millisecond(Some(5000)),
643                &DataType::Time64(TimeUnit::Nanosecond),
644            ),
645            Some(ScalarValue::Time64Nanosecond(Some(5000000000)))
646        );
647        assert_eq!(
648            safe_coerce_scalar(
649                &ScalarValue::Time64Microsecond(Some(5000000)),
650                &DataType::Time32(TimeUnit::Second),
651            ),
652            Some(ScalarValue::Time32Second(Some(5)))
653        );
654        assert_eq!(
655            safe_coerce_scalar(
656                &ScalarValue::Time64Microsecond(Some(5000000)),
657                &DataType::Time32(TimeUnit::Millisecond),
658            ),
659            Some(ScalarValue::Time32Millisecond(Some(5000)))
660        );
661        assert_eq!(
662            safe_coerce_scalar(
663                &ScalarValue::Time64Microsecond(Some(5000000)),
664                &DataType::Time64(TimeUnit::Microsecond),
665            ),
666            Some(ScalarValue::Time64Microsecond(Some(5000000)))
667        );
668        assert_eq!(
669            safe_coerce_scalar(
670                &ScalarValue::Time64Microsecond(Some(5000000)),
671                &DataType::Time64(TimeUnit::Nanosecond),
672            ),
673            Some(ScalarValue::Time64Nanosecond(Some(5000000000)))
674        );
675        assert_eq!(
676            safe_coerce_scalar(
677                &ScalarValue::Time64Nanosecond(Some(5000000000)),
678                &DataType::Time32(TimeUnit::Second),
679            ),
680            Some(ScalarValue::Time32Second(Some(5)))
681        );
682        assert_eq!(
683            safe_coerce_scalar(
684                &ScalarValue::Time64Nanosecond(Some(5000000000)),
685                &DataType::Time32(TimeUnit::Millisecond),
686            ),
687            Some(ScalarValue::Time32Millisecond(Some(5000)))
688        );
689        assert_eq!(
690            safe_coerce_scalar(
691                &ScalarValue::Time64Nanosecond(Some(5000000000)),
692                &DataType::Time64(TimeUnit::Microsecond),
693            ),
694            Some(ScalarValue::Time64Microsecond(Some(5000000)))
695        );
696        assert_eq!(
697            safe_coerce_scalar(
698                &ScalarValue::Time64Nanosecond(Some(5000000000)),
699                &DataType::Time64(TimeUnit::Nanosecond),
700            ),
701            Some(ScalarValue::Time64Nanosecond(Some(5000000000)))
702        );
703    }
704}