## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/physical-expr/src/expressions/try_cast.rs

    Line
    Count
    Source
    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;
    21
    use std::sync::Arc;
    22
    23
    use crate::PhysicalExpr;
    24
    use arrow::compute;
    25
    use arrow::compute::CastOptions;
    26
    use arrow::datatypes::{DataType, FieldRef, Schema};
    27
    use arrow::record_batch::RecordBatch;
    28
    use compute::can_cast_types;
    29
    use datafusion_common::format::DEFAULT_FORMAT_OPTIONS;
    30
    use datafusion_common::{not_impl_err, Result};
    31
    use datafusion_expr::ColumnarValue;
    32
    33
    /// TRY_CAST expression casts an expression to a specific data type and returns NULL on invalid cast
    34
    #[derive(Debug, Eq)]
    35
    pub struct TryCastExpr {
    36
        /// The expression to cast
    37
        expr: Arc<dyn PhysicalExpr>,
    38
        /// The data type to cast to
    39
        cast_type: DataType,
    40
    }
    41
    42
    // Manually derive PartialEq and Hash to work around https://github.com/rust-lang/rust/issues/78808
    43
    impl PartialEq for TryCastExpr {
    44
    0
        fn eq(&self, other: &Self) -> bool {
    45
    0
            self.expr.eq(&other.expr) && self.cast_type == other.cast_type
    46
    0
        }
    47
    }
    48
    49
    impl Hash for TryCastExpr {
    50
    0
        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
    51
    0
            self.expr.hash(state);
    52
    0
            self.cast_type.hash(state);
    53
    0
        }
    54
    }
    55
    56
    impl TryCastExpr {
    57
        /// Create a new CastExpr
    58
    483
        pub fn new(expr: Arc<dyn PhysicalExpr>, cast_type: DataType) -> Self {
    59
    483
            Self { expr, cast_type }
    60
    483
        }
    61
    62
        /// The expression to cast
    63
    0
        pub fn expr(&self) -> &Arc<dyn PhysicalExpr> {
    64
    0
            &self.expr
    65
    0
        }
    66
    67
        /// The data type to cast to
    68
    0
        pub fn cast_type(&self) -> &DataType {
    69
    0
            &self.cast_type
    70
    0
        }
    71
    }
    72
    73
    impl fmt::Display for TryCastExpr {
    74
    0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    75
    0
            write!(f, "TRY_CAST({} AS {:?})", self.expr, self.cast_type)
    76
    0
        }
    77
    }
    78
    79
    impl PhysicalExpr for TryCastExpr {
    80
        /// Return a reference to Any that can be used for downcasting
    81
    0
        fn as_any(&self) -> &dyn Any {
    82
    0
            self
    83
    0
        }
    84
    85
    482
        fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
    86
    482
            Ok(self.cast_type.clone())
    87
    482
        }
    88
    89
    0
        fn nullable(&self, _input_schema: &Schema) -> Result<bool> {
    90
    0
            Ok(true)
    91
    0
        }
    92
    93
    485
        fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {
    94
    485
            let value = self.expr.evaluate(batch)?0;
    95
    485
            let options = CastOptions {
    96
    485
                safe: true,
    97
    485
                format_options: DEFAULT_FORMAT_OPTIONS,
    98
    485
            };
    99
    485
            value.cast_to(&self.cast_type, Some(&options))
    100
    485
        }
    101
    102
    0
        fn return_field(&self, input_schema: &Schema) -> Result<FieldRef> {
    103
    0
            self.expr
    104
    0
                .return_field(input_schema)
    105
    0
                .map(|f| f.as_ref().clone().with_data_type(self.cast_type.clone()))
    106
    0
                .map(Arc::new)
    107
    0
        }
    108
    109
    0
        fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
    110
    0
            vec![&self.expr]
    111
    0
        }
    112
    113
    0
        fn with_new_children(
    114
    0
            self: Arc<Self>,
    115
    0
            children: Vec<Arc<dyn PhysicalExpr>>,
    116
    0
        ) -> Result<Arc<dyn PhysicalExpr>> {
    117
    0
            Ok(Arc::new(TryCastExpr::new(
    118
    0
                Arc::clone(&children[0]),
    119
    0
                self.cast_type.clone(),
    120
    0
            )))
    121
    0
        }
    122
    123
    0
        fn fmt_sql(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    124
    0
            write!(f, "TRY_CAST(")?;
    125
    0
            self.expr.fmt_sql(f)?;
    126
    0
            write!(f, " AS {:?})", self.cast_type)
    127
    0
        }
    128
    }
    129
    130
    /// Return a PhysicalExpression representing `expr` casted to
    131
    /// `cast_type`, if any casting is needed.
    132
    ///
    133
    /// Note that such casts may lose type information
    134
    755
    pub fn try_cast(
    135
    755
        expr: Arc<dyn PhysicalExpr>,
    136
    755
        input_schema: &Schema,
    137
    755
        cast_type: DataType,
    138
    755
    ) -> Result<Arc<dyn PhysicalExpr>> {
    139
    755
        let expr_type = expr.data_type(input_schema)?0;
    140
    755
        if expr_type == cast_type {
    141
    272
            Ok(Arc::clone(&expr))
    142
    483
        } else if can_cast_types(&expr_type, &cast_type) {
    143
    483
            Ok(Arc::new(TryCastExpr::new(expr, cast_type)))
    144
        } else {
    145
    0
            not_impl_err!("Unsupported TRY_CAST from {expr_type} to {cast_type}")
    146
        }
    147
    755
    }
    148
    149
    #[cfg(test)]
    150
    mod tests {
    151
        use super::*;
    152
        use crate::expressions::col;
    153
        use arrow::array::{
    154
            Decimal128Array, Decimal128Builder, StringArray, Time64NanosecondArray,
    155
        };
    156
        use arrow::{
    157
            array::{
    158
                Array, Float32Array, Float64Array, Int16Array, Int32Array, Int64Array,
    159
                Int8Array, TimestampNanosecondArray, UInt32Array,
    160
            },
    161
            datatypes::*,
    162
        };
    163
        use datafusion_physical_expr_common::physical_expr::fmt_sql;
    164
    165
        // runs an end-to-end test of physical type cast
    166
        // 1. construct a record batch with a column "a" of type A
    167
        // 2. construct a physical expression of TRY_CAST(a AS B)
    168
        // 3. evaluate the expression
    169
        // 4. verify that the resulting expression is of type B
    170
        // 5. verify that the resulting values are downcastable and correct
    171
        macro_rules! generic_decimal_to_other_test_cast {
    172
            ($DECIMAL_ARRAY:ident, $A_TYPE:expr, $TYPEARRAY:ident, $TYPE:expr, $VEC:expr) => {{
    173
                let schema = Schema::new(vec![Field::new("a", $A_TYPE, true)]);
    174
                let batch = RecordBatch::try_new(
    175
                    Arc::new(schema.clone()),
    176
                    vec![Arc::new($DECIMAL_ARRAY)],
    177
                )?;
    178
                // verify that we can construct the expression
    179
                let expression = try_cast(col("a", &schema)?, &schema, $TYPE)?;
    180
    181
                // verify that its display is correct
    182
                assert_eq!(
    183
                    format!("TRY_CAST(a@0 AS {:?})", $TYPE),
    184
                    format!("{}", expression)
    185
                );
    186
    187
                // verify that the expression's type is correct
    188
                assert_eq!(expression.data_type(&schema)?, $TYPE);
    189
    190
                // compute
    191
                let result = expression
    192
                    .evaluate(&batch)?
    193
                    .into_array(batch.num_rows())
    194
                    .expect("Failed to convert to array");
    195
    196
                // verify that the array's data_type is correct
    197
                assert_eq!(*result.data_type(), $TYPE);
    198
    199
                // verify that the data itself is downcastable
    200
                let result = result
    201
                    .as_any()
    202
                    .downcast_ref::<$TYPEARRAY>()
    203
                    .expect("failed to downcast");
    204
    205
                // verify that the result itself is correct
    206
                for (i, x) in $VEC.iter().enumerate() {
    207
                    match x {
    208
                        Some(x) => assert_eq!(result.value(i), *x),
    209
                        None => assert!(!result.is_valid(i)),
    210
                    }
    211
                }
    212
            }};
    213
        }
    214
    215
        // runs an end-to-end test of physical type cast
    216
        // 1. construct a record batch with a column "a" of type A
    217
        // 2. construct a physical expression of TRY_CAST(a AS B)
    218
        // 3. evaluate the expression
    219
        // 4. verify that the resulting expression is of type B
    220
        // 5. verify that the resulting values are downcastable and correct
    221
        macro_rules! generic_test_cast {
    222
            ($A_ARRAY:ident, $A_TYPE:expr, $A_VEC:expr, $TYPEARRAY:ident, $TYPE:expr, $VEC:expr) => {{
    223
                let schema = Schema::new(vec![Field::new("a", $A_TYPE, true)]);
    224
                let a_vec_len = $A_VEC.len();
    225
                let a = $A_ARRAY::from($A_VEC);
    226
                let batch =
    227
                    RecordBatch::try_new(Arc::new(schema.clone()), vec![Arc::new(a)])?;
    228
    229
                // verify that we can construct the expression
    230
                let expression = try_cast(col("a", &schema)?, &schema, $TYPE)?;
    231
    232
                // verify that its display is correct
    233
                assert_eq!(
    234
                    format!("TRY_CAST(a@0 AS {:?})", $TYPE),
    235
                    format!("{}", expression)
    236
                );
    237
    238
                // verify that the expression's type is correct
    239
                assert_eq!(expression.data_type(&schema)?, $TYPE);
    240
    241
                // compute
    242
                let result = expression
    243
                    .evaluate(&batch)?
    244
                    .into_array(batch.num_rows())
    245
                    .expect("Failed to convert to array");
    246
    247
                // verify that the array's data_type is correct
    248
                assert_eq!(*result.data_type(), $TYPE);
    249
    250
                // verify that the len is correct
    251
                assert_eq!(result.len(), a_vec_len);
    252
    253
                // verify that the data itself is downcastable
    254
                let result = result
    255
                    .as_any()
    256
                    .downcast_ref::<$TYPEARRAY>()
    257
                    .expect("failed to downcast");
    258
    259
                // verify that the result itself is correct
    260
                for (i, x) in $VEC.iter().enumerate() {
    261
                    match x {
    262
                        Some(x) => assert_eq!(result.value(i), *x),
    263
                        None => assert!(!result.is_valid(i)),
    264
                    }
    265
                }
    266
            }};
    267
        }
    268
    269
        #[test]
    270
    0
        fn test_try_cast_decimal_to_decimal() -> Result<()> {
    271
            // try cast one decimal data type to another decimal data type
    272
    0
            let array: Vec<i128> = vec![1234, 2222, 3, 4000, 5000];
    273
    0
            let decimal_array = create_decimal_array(&array, 10, 3);
    274
    0
            generic_decimal_to_other_test_cast!(
    275
                decimal_array,
    276
    0
                DataType::Decimal128(10, 3),
    277
                Decimal128Array,
    278
    0
                DataType::Decimal128(20, 6),
    279
    0
                [
    280
    0
                    Some(1_234_000),
    281
    0
                    Some(2_222_000),
    282
    0
                    Some(3_000),
    283
    0
                    Some(4_000_000),
    284
    0
                    Some(5_000_000),
    285
    0
                    None
    286
    0
                ]
    287
            );
    288
    289
    0
            let decimal_array = create_decimal_array(&array, 10, 3);
    290
    0
            generic_decimal_to_other_test_cast!(
    291
                decimal_array,
    292
    0
                DataType::Decimal128(10, 3),
    293
                Decimal128Array,
    294
    0
                DataType::Decimal128(10, 2),
    295
    0
                [Some(123), Some(222), Some(0), Some(400), Some(500), None]
    296
            );
    297
    298
    0
            Ok(())
    299
    0
        }
    300
    301
        #[test]
    302
    0
        fn test_try_cast_decimal_to_numeric() -> Result<()> {
    303
            // TODO we should add function to create Decimal128Array with value and metadata
    304
            // https://github.com/apache/arrow-rs/issues/1009
    305
    0
            let array: Vec<i128> = vec![1, 2, 3, 4, 5];
    306
    0
            let decimal_array = create_decimal_array(&array, 10, 0);
    307
            // decimal to i8
    308
    0
            generic_decimal_to_other_test_cast!(
    309
                decimal_array,
    310
    0
                DataType::Decimal128(10, 0),
    311
                Int8Array,
    312
    0
                DataType::Int8,
    313
    0
                [
    314
    0
                    Some(1_i8),
    315
    0
                    Some(2_i8),
    316
    0
                    Some(3_i8),
    317
    0
                    Some(4_i8),
    318
    0
                    Some(5_i8),
    319
    0
                    None
    320
    0
                ]
    321
            );
    322
    323
            // decimal to i16
    324
    0
            let decimal_array = create_decimal_array(&array, 10, 0);
    325
    0
            generic_decimal_to_other_test_cast!(
    326
                decimal_array,
    327
    0
                DataType::Decimal128(10, 0),
    328
                Int16Array,
    329
    0
                DataType::Int16,
    330
    0
                [
    331
    0
                    Some(1_i16),
    332
    0
                    Some(2_i16),
    333
    0
                    Some(3_i16),
    334
    0
                    Some(4_i16),
    335
    0
                    Some(5_i16),
    336
    0
                    None
    337
    0
                ]
    338
            );
    339
    340
            // decimal to i32
    341
    0
            let decimal_array = create_decimal_array(&array, 10, 0);
    342
    0
            generic_decimal_to_other_test_cast!(
    343
                decimal_array,
    344
    0
                DataType::Decimal128(10, 0),
    345
                Int32Array,
    346
    0
                DataType::Int32,
    347
    0
                [
    348
    0
                    Some(1_i32),
    349
    0
                    Some(2_i32),
    350
    0
                    Some(3_i32),
    351
    0
                    Some(4_i32),
    352
    0
                    Some(5_i32),
    353
    0
                    None
    354
    0
                ]
    355
            );
    356
    357
            // decimal to i64
    358
    0
            let decimal_array = create_decimal_array(&array, 10, 0);
    359
    0
            generic_decimal_to_other_test_cast!(
    360
                decimal_array,
    361
    0
                DataType::Decimal128(10, 0),
    362
                Int64Array,
    363
    0
                DataType::Int64,
    364
    0
                [
    365
    0
                    Some(1_i64),
    366
    0
                    Some(2_i64),
    367
    0
                    Some(3_i64),
    368
    0
                    Some(4_i64),
    369
    0
                    Some(5_i64),
    370
    0
                    None
    371
    0
                ]
    372
            );
    373
    374
            // decimal to float32
    375
    0
            let array: Vec<i128> = vec![1234, 2222, 3, 4000, 5000];
    376
    0
            let decimal_array = create_decimal_array(&array, 10, 3);
    377
    0
            generic_decimal_to_other_test_cast!(
    378
                decimal_array,
    379
    0
                DataType::Decimal128(10, 3),
    380
                Float32Array,
    381
    0
                DataType::Float32,
    382
    0
                [
    383
    0
                    Some(1.234_f32),
    384
    0
                    Some(2.222_f32),
    385
    0
                    Some(0.003_f32),
    386
    0
                    Some(4.0_f32),
    387
    0
                    Some(5.0_f32),
    388
    0
                    None
    389
    0
                ]
    390
            );
    391
            // decimal to float64
    392
    0
            let decimal_array = create_decimal_array(&array, 20, 6);
    393
    0
            generic_decimal_to_other_test_cast!(
    394
                decimal_array,
    395
    0
                DataType::Decimal128(20, 6),
    396
                Float64Array,
    397
    0
                DataType::Float64,
    398
    0
                [
    399
    0
                    Some(0.001234_f64),
    400
    0
                    Some(0.002222_f64),
    401
    0
                    Some(0.000003_f64),
    402
    0
                    Some(0.004_f64),
    403
    0
                    Some(0.005_f64),
    404
    0
                    None
    405
    0
                ]
    406
            );
    407
    408
    0
            Ok(())
    409
    0
        }
    410
    411
        #[test]
    412
    0
        fn test_try_cast_numeric_to_decimal() -> Result<()> {
    413
            // int8
    414
    0
            generic_test_cast!(
    415
                Int8Array,
    416
    0
                DataType::Int8,
    417
    0
                vec![1, 2, 3, 4, 5],
    418
                Decimal128Array,
    419
    0
                DataType::Decimal128(3, 0),
    420
    0
                [Some(1), Some(2), Some(3), Some(4), Some(5)]
    421
            );
    422
    423
            // int16
    424
    0
            generic_test_cast!(
    425
                Int16Array,
    426
    0
                DataType::Int16,
    427
    0
                vec![1, 2, 3, 4, 5],
    428
                Decimal128Array,
    429
    0
                DataType::Decimal128(5, 0),
    430
    0
                [Some(1), Some(2), Some(3), Some(4), Some(5)]
    431
            );
    432
    433
            // int32
    434
    0
            generic_test_cast!(
    435
                Int32Array,
    436
    0
                DataType::Int32,
    437
    0
                vec![1, 2, 3, 4, 5],
    438
                Decimal128Array,
    439
    0
                DataType::Decimal128(10, 0),
    440
    0
                [Some(1), Some(2), Some(3), Some(4), Some(5)]
    441
            );
    442
    443
            // int64
    444
    0
            generic_test_cast!(
    445
                Int64Array,
    446
    0
                DataType::Int64,
    447
    0
                vec![1, 2, 3, 4, 5],
    448
                Decimal128Array,
    449
    0
                DataType::Decimal128(20, 0),
    450
    0
                [Some(1), Some(2), Some(3), Some(4), Some(5)]
    451
            );
    452
    453
            // int64 to different scale
    454
    0
            generic_test_cast!(
    455
                Int64Array,
    456
    0
                DataType::Int64,
    457
    0
                vec![1, 2, 3, 4, 5],
    458
                Decimal128Array,
    459
    0
                DataType::Decimal128(20, 2),
    460
    0
                [Some(100), Some(200), Some(300), Some(400), Some(500)]
    461
            );
    462
    463
            // float32
    464
    0
            generic_test_cast!(
    465
                Float32Array,
    466
    0
                DataType::Float32,
    467
    0
                vec![1.5, 2.5, 3.0, 1.123_456_8, 5.50],
    468
                Decimal128Array,
    469
    0
                DataType::Decimal128(10, 2),
    470
    0
                [Some(150), Some(250), Some(300), Some(112), Some(550)]
    471
            );
    472
    473
            // float64
    474
    0
            generic_test_cast!(
    475
                Float64Array,
    476
    0
                DataType::Float64,
    477
    0
                vec![1.5, 2.5, 3.0, 1.123_456_8, 5.50],
    478
                Decimal128Array,
    479
    0
                DataType::Decimal128(20, 4),
    480
    0
                [
    481
    0
                    Some(15000),
    482
    0
                    Some(25000),
    483
    0
                    Some(30000),
    484
    0
                    Some(11235),
    485
    0
                    Some(55000)
    486
    0
                ]
    487
            );
    488
    0
            Ok(())
    489
    0
        }
    490
    491
        #[test]
    492
    0
        fn test_cast_i32_u32() -> Result<()> {
    493
    0
            generic_test_cast!(
    494
                Int32Array,
    495
    0
                DataType::Int32,
    496
    0
                vec![1, 2, 3, 4, 5],
    497
                UInt32Array,
    498
    0
                DataType::UInt32,
    499
    0
                [
    500
    0
                    Some(1_u32),
    501
    0
                    Some(2_u32),
    502
    0
                    Some(3_u32),
    503
    0
                    Some(4_u32),
    504
    0
                    Some(5_u32)
    505
    0
                ]
    506
            );
    507
    0
            Ok(())
    508
    0
        }
    509
    510
        #[test]
    511
    0
        fn test_cast_i32_utf8() -> Result<()> {
    512
    0
            generic_test_cast!(
    513
                Int32Array,
    514
    0
                DataType::Int32,
    515
    0
                vec![1, 2, 3, 4, 5],
    516
                StringArray,
    517
    0
                DataType::Utf8,
    518
    0
                [Some("1"), Some("2"), Some("3"), Some("4"), Some("5")]
    519
            );
    520
    0
            Ok(())
    521
    0
        }
    522
    523
        #[test]
    524
    0
        fn test_try_cast_utf8_i32() -> Result<()> {
    525
    0
            generic_test_cast!(
    526
                StringArray,
    527
    0
                DataType::Utf8,
    528
    0
                vec!["a", "2", "3", "b", "5"],
    529
                Int32Array,
    530
    0
                DataType::Int32,
    531
    0
                [None, Some(2), Some(3), None, Some(5)]
    532
            );
    533
    0
            Ok(())
    534
    0
        }
    535
    536
        #[test]
    537
    0
        fn test_cast_i64_t64() -> Result<()> {
    538
    0
            let original = vec![1, 2, 3, 4, 5];
    539
    0
            let expected: Vec<Option<i64>> = original
    540
    0
                .iter()
    541
    0
                .map(|i| Some(Time64NanosecondArray::from(vec![*i]).value(0)))
    542
    0
                .collect();
    543
    0
            generic_test_cast!(
    544
                Int64Array,
    545
    0
                DataType::Int64,
    546
    0
                original,
    547
                TimestampNanosecondArray,
    548
    0
                DataType::Timestamp(TimeUnit::Nanosecond, None),
    549
    0
                expected
    550
            );
    551
    0
            Ok(())
    552
    0
        }
    553
    554
        #[test]
    555
    0
        fn invalid_cast() {
    556
            // Ensure a useful error happens at plan time if invalid casts are used
    557
    0
            let schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
    558
    559
    0
            let result = try_cast(
    560
    0
                col("a", &schema).unwrap(),
    561
    0
                &schema,
    562
    0
                DataType::Interval(IntervalUnit::MonthDayNano),
    563
            );
    564
    0
            result.expect_err("expected Invalid TRY_CAST");
    565
    0
        }
    566
    567
        // create decimal array with the specified precision and scale
    568
    0
        fn create_decimal_array(array: &[i128], precision: u8, scale: i8) -> Decimal128Array {
    569
    0
            let mut decimal_builder = Decimal128Builder::with_capacity(array.len());
    570
    0
            for value in array {
    571
    0
                decimal_builder.append_value(*value);
    572
    0
            }
    573
    0
            decimal_builder.append_null();
    574
    0
            decimal_builder
    575
    0
                .finish()
    576
    0
                .with_precision_and_scale(precision, scale)
    577
    0
                .unwrap()
    578
    0
        }
    579
    580
        #[test]
    581
    0
        fn test_fmt_sql() -> Result<()> {
    582
    0
            let schema = Schema::new(vec![Field::new("a", DataType::Int32, true)]);
    583
    584
            // Test numeric casting
    585
    0
            let expr = try_cast(col("a", &schema)?, &schema, DataType::Int64)?;
    586
    0
            let display_string = expr.to_string();
    587
    0
            assert_eq!(display_string, "TRY_CAST(a@0 AS Int64)");
    588
    0
            let sql_string = fmt_sql(expr.as_ref()).to_string();
    589
    0
            assert_eq!(sql_string, "TRY_CAST(a AS Int64)");
    590
    591
            // Test string casting
    592
    0
            let schema = Schema::new(vec![Field::new("b", DataType::Utf8, true)]);
    593
    0
            let expr = try_cast(col("b", &schema)?, &schema, DataType::Int32)?;
    594
    0
            let display_string = expr.to_string();
    595
    0
            assert_eq!(display_string, "TRY_CAST(b@0 AS Int32)");
    596
    0
            let sql_string = fmt_sql(expr.as_ref()).to_string();
    597
    0
            assert_eq!(sql_string, "TRY_CAST(b AS Int32)");
    598
    599
    0
            Ok(())
    600
    0
        }
    601
    }