Coverage Report

Created: 2024-10-13 08:39

/Users/andrewlamb/Software/datafusion/datafusion/physical-expr/src/expressions/cast.rs
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
use std::any::Any;
19
use std::fmt;
20
use std::hash::{Hash, Hasher};
21
use std::sync::Arc;
22
23
use crate::physical_expr::{down_cast_any_ref, PhysicalExpr};
24
25
use arrow::compute::{can_cast_types, CastOptions};
26
use arrow::datatypes::{DataType, DataType::*, Schema};
27
use arrow::record_batch::RecordBatch;
28
use datafusion_common::format::DEFAULT_FORMAT_OPTIONS;
29
use datafusion_common::{not_impl_err, Result};
30
use datafusion_expr_common::columnar_value::ColumnarValue;
31
use datafusion_expr_common::interval_arithmetic::Interval;
32
use datafusion_expr_common::sort_properties::ExprProperties;
33
34
const DEFAULT_CAST_OPTIONS: CastOptions<'static> = CastOptions {
35
    safe: false,
36
    format_options: DEFAULT_FORMAT_OPTIONS,
37
};
38
39
const DEFAULT_SAFE_CAST_OPTIONS: CastOptions<'static> = CastOptions {
40
    safe: true,
41
    format_options: DEFAULT_FORMAT_OPTIONS,
42
};
43
44
/// CAST expression casts an expression to a specific data type and returns a runtime error on invalid cast
45
#[derive(Debug, Clone)]
46
pub struct CastExpr {
47
    /// The expression to cast
48
    pub expr: Arc<dyn PhysicalExpr>,
49
    /// The data type to cast to
50
    cast_type: DataType,
51
    /// Cast options
52
    cast_options: CastOptions<'static>,
53
}
54
55
impl CastExpr {
56
    /// Create a new CastExpr
57
85
    pub fn new(
58
85
        expr: Arc<dyn PhysicalExpr>,
59
85
        cast_type: DataType,
60
85
        cast_options: Option<CastOptions<'static>>,
61
85
    ) -> Self {
62
85
        Self {
63
85
            expr,
64
85
            cast_type,
65
85
            cast_options: cast_options.unwrap_or(DEFAULT_CAST_OPTIONS),
66
85
        }
67
85
    }
68
69
    /// The expression to cast
70
0
    pub fn expr(&self) -> &Arc<dyn PhysicalExpr> {
71
0
        &self.expr
72
0
    }
73
74
    /// The data type to cast to
75
0
    pub fn cast_type(&self) -> &DataType {
76
0
        &self.cast_type
77
0
    }
78
79
    /// The cast options
80
0
    pub fn cast_options(&self) -> &CastOptions<'static> {
81
0
        &self.cast_options
82
0
    }
83
0
    pub fn is_bigger_cast(&self, src: DataType) -> bool {
84
0
        if src == self.cast_type {
85
0
            return true;
86
0
        }
87
0
        matches!(
88
0
            (src, &self.cast_type),
89
            (Int8, Int16 | Int32 | Int64)
90
                | (Int16, Int32 | Int64)
91
                | (Int32, Int64)
92
                | (UInt8, UInt16 | UInt32 | UInt64)
93
                | (UInt16, UInt32 | UInt64)
94
                | (UInt32, UInt64)
95
                | (
96
                    Int8 | Int16 | Int32 | UInt8 | UInt16 | UInt32,
97
                    Float32 | Float64
98
                )
99
                | (Int64 | UInt64, Float64)
100
                | (Utf8, LargeUtf8)
101
        )
102
0
    }
103
}
104
105
impl fmt::Display for CastExpr {
106
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107
0
        write!(f, "CAST({} AS {:?})", self.expr, self.cast_type)
108
0
    }
109
}
110
111
impl PhysicalExpr for CastExpr {
112
    /// Return a reference to Any that can be used for downcasting
113
2.31k
    fn as_any(&self) -> &dyn Any {
114
2.31k
        self
115
2.31k
    }
116
117
3.24k
    fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
118
3.24k
        Ok(self.cast_type.clone())
119
3.24k
    }
120
121
0
    fn nullable(&self, input_schema: &Schema) -> Result<bool> {
122
0
        self.expr.nullable(input_schema)
123
0
    }
124
125
2.38k
    fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {
126
2.38k
        let value = self.expr.evaluate(batch)
?0
;
127
2.38k
        value.cast_to(&self.cast_type, Some(&self.cast_options))
128
2.38k
    }
129
130
808
    fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
131
808
        vec![&self.expr]
132
808
    }
133
134
0
    fn with_new_children(
135
0
        self: Arc<Self>,
136
0
        children: Vec<Arc<dyn PhysicalExpr>>,
137
0
    ) -> Result<Arc<dyn PhysicalExpr>> {
138
0
        Ok(Arc::new(CastExpr::new(
139
0
            Arc::clone(&children[0]),
140
0
            self.cast_type.clone(),
141
0
            Some(self.cast_options.clone()),
142
0
        )))
143
0
    }
144
145
776
    fn evaluate_bounds(&self, children: &[&Interval]) -> Result<Interval> {
146
776
        // Cast current node's interval to the right type:
147
776
        children[0].cast_to(&self.cast_type, &self.cast_options)
148
776
    }
149
150
776
    fn propagate_constraints(
151
776
        &self,
152
776
        interval: &Interval,
153
776
        children: &[&Interval],
154
776
    ) -> Result<Option<Vec<Interval>>> {
155
776
        let child_interval = children[0];
156
776
        // Get child's datatype:
157
776
        let cast_type = child_interval.data_type();
158
776
        Ok(Some(vec![
159
776
            interval.cast_to(&cast_type, &DEFAULT_SAFE_CAST_OPTIONS)
?0
160
        ]))
161
776
    }
162
163
0
    fn dyn_hash(&self, state: &mut dyn Hasher) {
164
0
        let mut s = state;
165
0
        self.expr.hash(&mut s);
166
0
        self.cast_type.hash(&mut s);
167
0
        self.cast_options.hash(&mut s);
168
0
    }
169
170
    /// A [`CastExpr`] preserves the ordering of its child if the cast is done
171
    /// under the same datatype family.
172
0
    fn get_properties(&self, children: &[ExprProperties]) -> Result<ExprProperties> {
173
0
        let source_datatype = children[0].range.data_type();
174
0
        let target_type = &self.cast_type;
175
176
0
        let unbounded = Interval::make_unbounded(target_type)?;
177
0
        if (source_datatype.is_numeric() || source_datatype == Boolean)
178
0
            && target_type.is_numeric()
179
0
            || source_datatype.is_temporal() && target_type.is_temporal()
180
0
            || source_datatype.eq(target_type)
181
        {
182
0
            Ok(children[0].clone().with_range(unbounded))
183
        } else {
184
0
            Ok(ExprProperties::new_unknown().with_range(unbounded))
185
        }
186
0
    }
187
}
188
189
impl PartialEq<dyn Any> for CastExpr {
190
2.85k
    fn eq(&self, other: &dyn Any) -> bool {
191
2.85k
        down_cast_any_ref(other)
192
2.85k
            .downcast_ref::<Self>()
193
2.85k
            .map(|x| {
194
721
                self.expr.eq(&x.expr)
195
289
                    && self.cast_type == x.cast_type
196
289
                    && self.cast_options == x.cast_options
197
2.85k
            
}721
)
198
2.85k
            .unwrap_or(false)
199
2.85k
    }
200
}
201
202
/// Return a PhysicalExpression representing `expr` casted to
203
/// `cast_type`, if any casting is needed.
204
///
205
/// Note that such casts may lose type information
206
85
pub fn cast_with_options(
207
85
    expr: Arc<dyn PhysicalExpr>,
208
85
    input_schema: &Schema,
209
85
    cast_type: DataType,
210
85
    cast_options: Option<CastOptions<'static>>,
211
85
) -> Result<Arc<dyn PhysicalExpr>> {
212
85
    let expr_type = expr.data_type(input_schema)
?0
;
213
85
    if expr_type == cast_type {
214
0
        Ok(Arc::clone(&expr))
215
85
    } else if can_cast_types(&expr_type, &cast_type) {
216
85
        Ok(Arc::new(CastExpr::new(expr, cast_type, cast_options)))
217
    } else {
218
0
        not_impl_err!("Unsupported CAST from {expr_type:?} to {cast_type:?}")
219
    }
220
85
}
221
222
/// Return a PhysicalExpression representing `expr` casted to
223
/// `cast_type`, if any casting is needed.
224
///
225
/// Note that such casts may lose type information
226
85
pub fn cast(
227
85
    expr: Arc<dyn PhysicalExpr>,
228
85
    input_schema: &Schema,
229
85
    cast_type: DataType,
230
85
) -> Result<Arc<dyn PhysicalExpr>> {
231
85
    cast_with_options(expr, input_schema, cast_type, None)
232
85
}
233
234
#[cfg(test)]
235
mod tests {
236
    use super::*;
237
238
    use crate::expressions::column::col;
239
240
    use arrow::{
241
        array::{
242
            Array, Decimal128Array, Float32Array, Float64Array, Int16Array, Int32Array,
243
            Int64Array, Int8Array, StringArray, Time64NanosecondArray,
244
            TimestampNanosecondArray, UInt32Array,
245
        },
246
        datatypes::*,
247
    };
248
249
    // runs an end-to-end test of physical type cast
250
    // 1. construct a record batch with a column "a" of type A
251
    // 2. construct a physical expression of CAST(a AS B)
252
    // 3. evaluate the expression
253
    // 4. verify that the resulting expression is of type B
254
    // 5. verify that the resulting values are downcastable and correct
255
    macro_rules! generic_decimal_to_other_test_cast {
256
        ($DECIMAL_ARRAY:ident, $A_TYPE:expr, $TYPEARRAY:ident, $TYPE:expr, $VEC:expr,$CAST_OPTIONS:expr) => {{
257
            let schema = Schema::new(vec![Field::new("a", $A_TYPE, true)]);
258
            let batch = RecordBatch::try_new(
259
                Arc::new(schema.clone()),
260
                vec![Arc::new($DECIMAL_ARRAY)],
261
            )?;
262
            // verify that we can construct the expression
263
            let expression =
264
                cast_with_options(col("a", &schema)?, &schema, $TYPE, $CAST_OPTIONS)?;
265
266
            // verify that its display is correct
267
            assert_eq!(
268
                format!("CAST(a@0 AS {:?})", $TYPE),
269
                format!("{}", expression)
270
            );
271
272
            // verify that the expression's type is correct
273
            assert_eq!(expression.data_type(&schema)?, $TYPE);
274
275
            // compute
276
            let result = expression
277
                .evaluate(&batch)?
278
                .into_array(batch.num_rows())
279
                .expect("Failed to convert to array");
280
281
            // verify that the array's data_type is correct
282
            assert_eq!(*result.data_type(), $TYPE);
283
284
            // verify that the data itself is downcastable
285
            let result = result
286
                .as_any()
287
                .downcast_ref::<$TYPEARRAY>()
288
                .expect("failed to downcast");
289
290
            // verify that the result itself is correct
291
            for (i, x) in $VEC.iter().enumerate() {
292
                match x {
293
                    Some(x) => assert_eq!(result.value(i), *x),
294
                    None => assert!(!result.is_valid(i)),
295
                }
296
            }
297
        }};
298
    }
299
300
    // runs an end-to-end test of physical type cast
301
    // 1. construct a record batch with a column "a" of type A
302
    // 2. construct a physical expression of CAST(a AS B)
303
    // 3. evaluate the expression
304
    // 4. verify that the resulting expression is of type B
305
    // 5. verify that the resulting values are downcastable and correct
306
    macro_rules! generic_test_cast {
307
        ($A_ARRAY:ident, $A_TYPE:expr, $A_VEC:expr, $TYPEARRAY:ident, $TYPE:expr, $VEC:expr, $CAST_OPTIONS:expr) => {{
308
            let schema = Schema::new(vec![Field::new("a", $A_TYPE, true)]);
309
            let a_vec_len = $A_VEC.len();
310
            let a = $A_ARRAY::from($A_VEC);
311
            let batch =
312
                RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
313
314
            // verify that we can construct the expression
315
            let expression =
316
                cast_with_options(col("a", &schema)?, &schema, $TYPE, $CAST_OPTIONS)?;
317
318
            // verify that its display is correct
319
            assert_eq!(
320
                format!("CAST(a@0 AS {:?})", $TYPE),
321
                format!("{}", expression)
322
            );
323
324
            // verify that the expression's type is correct
325
            assert_eq!(expression.data_type(&schema)?, $TYPE);
326
327
            // compute
328
            let result = expression
329
                .evaluate(&batch)?
330
                .into_array(batch.num_rows())
331
                .expect("Failed to convert to array");
332
333
            // verify that the array's data_type is correct
334
            assert_eq!(*result.data_type(), $TYPE);
335
336
            // verify that the len is correct
337
            assert_eq!(result.len(), a_vec_len);
338
339
            // verify that the data itself is downcastable
340
            let result = result
341
                .as_any()
342
                .downcast_ref::<$TYPEARRAY>()
343
                .expect("failed to downcast");
344
345
            // verify that the result itself is correct
346
            for (i, x) in $VEC.iter().enumerate() {
347
                match x {
348
                    Some(x) => assert_eq!(result.value(i), *x),
349
                    None => assert!(!result.is_valid(i)),
350
                }
351
            }
352
        }};
353
    }
354
355
    #[test]
356
    fn test_cast_decimal_to_decimal() -> Result<()> {
357
        let array = vec![
358
            Some(1234),
359
            Some(2222),
360
            Some(3),
361
            Some(4000),
362
            Some(5000),
363
            None,
364
        ];
365
366
        let decimal_array = array
367
            .clone()
368
            .into_iter()
369
            .collect::<Decimal128Array>()
370
            .with_precision_and_scale(10, 3)?;
371
372
        generic_decimal_to_other_test_cast!(
373
            decimal_array,
374
            Decimal128(10, 3),
375
            Decimal128Array,
376
            Decimal128(20, 6),
377
            [
378
                Some(1_234_000),
379
                Some(2_222_000),
380
                Some(3_000),
381
                Some(4_000_000),
382
                Some(5_000_000),
383
                None
384
            ],
385
            None
386
        );
387
388
        let decimal_array = array
389
            .into_iter()
390
            .collect::<Decimal128Array>()
391
            .with_precision_and_scale(10, 3)?;
392
393
        generic_decimal_to_other_test_cast!(
394
            decimal_array,
395
            Decimal128(10, 3),
396
            Decimal128Array,
397
            Decimal128(10, 2),
398
            [Some(123), Some(222), Some(0), Some(400), Some(500), None],
399
            None
400
        );
401
402
        Ok(())
403
    }
404
405
    #[test]
406
    fn test_cast_decimal_to_numeric() -> Result<()> {
407
        let array = vec![Some(1), Some(2), Some(3), Some(4), Some(5), None];
408
        // decimal to i8
409
        let decimal_array = array
410
            .clone()
411
            .into_iter()
412
            .collect::<Decimal128Array>()
413
            .with_precision_and_scale(10, 0)?;
414
        generic_decimal_to_other_test_cast!(
415
            decimal_array,
416
            Decimal128(10, 0),
417
            Int8Array,
418
            Int8,
419
            [
420
                Some(1_i8),
421
                Some(2_i8),
422
                Some(3_i8),
423
                Some(4_i8),
424
                Some(5_i8),
425
                None
426
            ],
427
            None
428
        );
429
430
        // decimal to i16
431
        let decimal_array = array
432
            .clone()
433
            .into_iter()
434
            .collect::<Decimal128Array>()
435
            .with_precision_and_scale(10, 0)?;
436
        generic_decimal_to_other_test_cast!(
437
            decimal_array,
438
            Decimal128(10, 0),
439
            Int16Array,
440
            Int16,
441
            [
442
                Some(1_i16),
443
                Some(2_i16),
444
                Some(3_i16),
445
                Some(4_i16),
446
                Some(5_i16),
447
                None
448
            ],
449
            None
450
        );
451
452
        // decimal to i32
453
        let decimal_array = array
454
            .clone()
455
            .into_iter()
456
            .collect::<Decimal128Array>()
457
            .with_precision_and_scale(10, 0)?;
458
        generic_decimal_to_other_test_cast!(
459
            decimal_array,
460
            Decimal128(10, 0),
461
            Int32Array,
462
            Int32,
463
            [
464
                Some(1_i32),
465
                Some(2_i32),
466
                Some(3_i32),
467
                Some(4_i32),
468
                Some(5_i32),
469
                None
470
            ],
471
            None
472
        );
473
474
        // decimal to i64
475
        let decimal_array = array
476
            .into_iter()
477
            .collect::<Decimal128Array>()
478
            .with_precision_and_scale(10, 0)?;
479
        generic_decimal_to_other_test_cast!(
480
            decimal_array,
481
            Decimal128(10, 0),
482
            Int64Array,
483
            Int64,
484
            [
485
                Some(1_i64),
486
                Some(2_i64),
487
                Some(3_i64),
488
                Some(4_i64),
489
                Some(5_i64),
490
                None
491
            ],
492
            None
493
        );
494
495
        // decimal to float32
496
        let array = vec![
497
            Some(1234),
498
            Some(2222),
499
            Some(3),
500
            Some(4000),
501
            Some(5000),
502
            None,
503
        ];
504
        let decimal_array = array
505
            .clone()
506
            .into_iter()
507
            .collect::<Decimal128Array>()
508
            .with_precision_and_scale(10, 3)?;
509
        generic_decimal_to_other_test_cast!(
510
            decimal_array,
511
            Decimal128(10, 3),
512
            Float32Array,
513
            Float32,
514
            [
515
                Some(1.234_f32),
516
                Some(2.222_f32),
517
                Some(0.003_f32),
518
                Some(4.0_f32),
519
                Some(5.0_f32),
520
                None
521
            ],
522
            None
523
        );
524
525
        // decimal to float64
526
        let decimal_array = array
527
            .into_iter()
528
            .collect::<Decimal128Array>()
529
            .with_precision_and_scale(20, 6)?;
530
        generic_decimal_to_other_test_cast!(
531
            decimal_array,
532
            Decimal128(20, 6),
533
            Float64Array,
534
            Float64,
535
            [
536
                Some(0.001234_f64),
537
                Some(0.002222_f64),
538
                Some(0.000003_f64),
539
                Some(0.004_f64),
540
                Some(0.005_f64),
541
                None
542
            ],
543
            None
544
        );
545
        Ok(())
546
    }
547
548
    #[test]
549
    fn test_cast_numeric_to_decimal() -> Result<()> {
550
        // int8
551
        generic_test_cast!(
552
            Int8Array,
553
            Int8,
554
            vec![1, 2, 3, 4, 5],
555
            Decimal128Array,
556
            Decimal128(3, 0),
557
            [Some(1), Some(2), Some(3), Some(4), Some(5)],
558
            None
559
        );
560
561
        // int16
562
        generic_test_cast!(
563
            Int16Array,
564
            Int16,
565
            vec![1, 2, 3, 4, 5],
566
            Decimal128Array,
567
            Decimal128(5, 0),
568
            [Some(1), Some(2), Some(3), Some(4), Some(5)],
569
            None
570
        );
571
572
        // int32
573
        generic_test_cast!(
574
            Int32Array,
575
            Int32,
576
            vec![1, 2, 3, 4, 5],
577
            Decimal128Array,
578
            Decimal128(10, 0),
579
            [Some(1), Some(2), Some(3), Some(4), Some(5)],
580
            None
581
        );
582
583
        // int64
584
        generic_test_cast!(
585
            Int64Array,
586
            Int64,
587
            vec![1, 2, 3, 4, 5],
588
            Decimal128Array,
589
            Decimal128(20, 0),
590
            [Some(1), Some(2), Some(3), Some(4), Some(5)],
591
            None
592
        );
593
594
        // int64 to different scale
595
        generic_test_cast!(
596
            Int64Array,
597
            Int64,
598
            vec![1, 2, 3, 4, 5],
599
            Decimal128Array,
600
            Decimal128(20, 2),
601
            [Some(100), Some(200), Some(300), Some(400), Some(500)],
602
            None
603
        );
604
605
        // float32
606
        generic_test_cast!(
607
            Float32Array,
608
            Float32,
609
            vec![1.5, 2.5, 3.0, 1.123_456_8, 5.50],
610
            Decimal128Array,
611
            Decimal128(10, 2),
612
            [Some(150), Some(250), Some(300), Some(112), Some(550)],
613
            None
614
        );
615
616
        // float64
617
        generic_test_cast!(
618
            Float64Array,
619
            Float64,
620
            vec![1.5, 2.5, 3.0, 1.123_456_8, 5.50],
621
            Decimal128Array,
622
            Decimal128(20, 4),
623
            [
624
                Some(15000),
625
                Some(25000),
626
                Some(30000),
627
                Some(11235),
628
                Some(55000)
629
            ],
630
            None
631
        );
632
        Ok(())
633
    }
634
635
    #[test]
636
    fn test_cast_i32_u32() -> Result<()> {
637
        generic_test_cast!(
638
            Int32Array,
639
            Int32,
640
            vec![1, 2, 3, 4, 5],
641
            UInt32Array,
642
            UInt32,
643
            [
644
                Some(1_u32),
645
                Some(2_u32),
646
                Some(3_u32),
647
                Some(4_u32),
648
                Some(5_u32)
649
            ],
650
            None
651
        );
652
        Ok(())
653
    }
654
655
    #[test]
656
    fn test_cast_i32_utf8() -> Result<()> {
657
        generic_test_cast!(
658
            Int32Array,
659
            Int32,
660
            vec![1, 2, 3, 4, 5],
661
            StringArray,
662
            Utf8,
663
            [Some("1"), Some("2"), Some("3"), Some("4"), Some("5")],
664
            None
665
        );
666
        Ok(())
667
    }
668
669
    #[test]
670
    fn test_cast_i64_t64() -> Result<()> {
671
        let original = vec![1, 2, 3, 4, 5];
672
        let expected: Vec<Option<i64>> = original
673
            .iter()
674
            .map(|i| Some(Time64NanosecondArray::from(vec![*i]).value(0)))
675
            .collect();
676
        generic_test_cast!(
677
            Int64Array,
678
            Int64,
679
            original,
680
            TimestampNanosecondArray,
681
            Timestamp(TimeUnit::Nanosecond, None),
682
            expected,
683
            None
684
        );
685
        Ok(())
686
    }
687
688
    #[test]
689
    fn invalid_cast() {
690
        // Ensure a useful error happens at plan time if invalid casts are used
691
        let schema = Schema::new(vec![Field::new("a", Int32, false)]);
692
693
        let result = cast(
694
            col("a", &schema).unwrap(),
695
            &schema,
696
            DataType::Interval(IntervalUnit::MonthDayNano),
697
        );
698
        result.expect_err("expected Invalid CAST");
699
    }
700
701
    #[test]
702
    fn invalid_cast_with_options_error() -> Result<()> {
703
        // Ensure a useful error happens at plan time if invalid casts are used
704
        let schema = Schema::new(vec![Field::new("a", Utf8, false)]);
705
        let a = StringArray::from(vec!["9.1"]);
706
        let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
707
        let expression = cast_with_options(col("a", &schema)?, &schema, Int32, None)?;
708
        let result = expression.evaluate(&batch);
709
710
        match result {
711
            Ok(_) => panic!("expected error"),
712
            Err(e) => {
713
                assert!(e
714
                    .to_string()
715
                    .contains("Cannot cast string '9.1' to value of Int32 type"))
716
            }
717
        }
718
        Ok(())
719
    }
720
721
    #[test]
722
    #[ignore] // TODO: https://github.com/apache/datafusion/issues/5396
723
    fn test_cast_decimal() -> Result<()> {
724
        let schema = Schema::new(vec![Field::new("a", Int64, false)]);
725
        let a = Int64Array::from(vec![100]);
726
        let batch = RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
727
        let expression =
728
            cast_with_options(col("a", &schema)?, &schema, Decimal128(38, 38), None)?;
729
        expression.evaluate(&batch)?;
730
        Ok(())
731
    }
732
}