diff --git a/datafusion/physical-expr/src/expressions/cast.rs b/datafusion/physical-expr/src/expressions/cast.rs index 7eda5fb4beaa..8a093e0ae92e 100644 --- a/datafusion/physical-expr/src/expressions/cast.rs +++ b/datafusion/physical-expr/src/expressions/cast.rs @@ -242,6 +242,7 @@ mod tests { }, datatypes::*, }; + use datafusion_common::assert_contains; // runs an end-to-end test of physical type cast // 1. construct a record batch with a column "a" of type A @@ -399,6 +400,45 @@ mod tests { Ok(()) } + #[test] + fn test_cast_decimal_to_decimal_overflow() -> Result<()> { + let array = vec![Some(123456789)]; + + let decimal_array = array + .clone() + .into_iter() + .collect::() + .with_precision_and_scale(10, 3)?; + + let schema = Schema::new(vec![Field::new("a", Decimal128(10, 3), false)]); + let batch = RecordBatch::try_new( + Arc::new(schema.clone()), + vec![Arc::new(decimal_array)], + )?; + let expression = + cast_with_options(col("a", &schema)?, &schema, Decimal128(6, 2), None)?; + let e = expression.evaluate(&batch).unwrap_err(); // panics on OK + assert_contains!( + e.to_string(), + "Arrow error: Invalid argument error: 12345679 is too large to store in a Decimal128 of precision 6. Max is 999999" + ); + + let expression_safe = cast_with_options( + col("a", &schema)?, + &schema, + Decimal128(6, 2), + Some(DEFAULT_SAFE_CAST_OPTIONS), + )?; + let result_safe = expression_safe + .evaluate(&batch)? + .into_array(batch.num_rows()) + .expect("failed to convert to array"); + + assert!(result_safe.is_null(0)); + + Ok(()) + } + #[test] fn test_cast_decimal_to_numeric() -> Result<()> { let array = vec![Some(1), Some(2), Some(3), Some(4), Some(5), None];