diff --git a/crates/polars-core/src/chunked_array/cast.rs b/crates/polars-core/src/chunked_array/cast.rs index ea74c39e64e7..ceb73d492d0b 100644 --- a/crates/polars-core/src/chunked_array/cast.rs +++ b/crates/polars-core/src/chunked_array/cast.rs @@ -51,7 +51,7 @@ pub(crate) fn cast_chunks( let check_nulls = matches!(options, CastOptions::Strict); let options = options.into(); - let arrow_dtype = dtype.to_arrow(true); + let arrow_dtype = dtype.try_to_arrow(true)?; chunks .iter() .map(|arr| { diff --git a/crates/polars-core/src/datatypes/dtype.rs b/crates/polars-core/src/datatypes/dtype.rs index 0144af1537dd..44a2a82d94c8 100644 --- a/crates/polars-core/src/datatypes/dtype.rs +++ b/crates/polars-core/src/datatypes/dtype.rs @@ -55,6 +55,7 @@ pub enum DataType { Float64, /// Fixed point decimal type optional precision and non-negative scale. /// This is backed by a signed 128-bit integer which allows for up to 38 significant digits. + /// Meaning max precision is 38. #[cfg(feature = "dtype-decimal")] Decimal(Option, Option), // precision/scale; scale being None means "infer" /// String data @@ -542,11 +543,15 @@ impl DataType { Float32 => Ok(ArrowDataType::Float32), Float64 => Ok(ArrowDataType::Float64), #[cfg(feature = "dtype-decimal")] - // note: what else can we do here other than setting precision to 38?.. - Decimal(precision, scale) => Ok(ArrowDataType::Decimal( - (*precision).unwrap_or(38), - scale.unwrap_or(0), // and what else can we do here? - )), + Decimal(precision, scale) => { + let precision = (*precision).unwrap_or(38); + polars_ensure!(precision <= 38 && precision > 0, InvalidOperation: "decimal precision should be <= 38 & >= 1"); + + Ok(ArrowDataType::Decimal( + precision, + scale.unwrap_or(0), // and what else can we do here? + )) + }, String => { let dt = if pl_flavor { ArrowDataType::Utf8View diff --git a/py-polars/tests/unit/datatypes/test_decimal.py b/py-polars/tests/unit/datatypes/test_decimal.py index 7c18886a9975..96a4ce413149 100644 --- a/py-polars/tests/unit/datatypes/test_decimal.py +++ b/py-polars/tests/unit/datatypes/test_decimal.py @@ -472,3 +472,10 @@ def test_decimal_supertype() -> None: pl.col("column_0").cast(pl.Decimal(scale=6)) * 1 ) assert q.collect().dtypes[0].is_decimal() + + +def test_decimal_raise_oob_precision() -> None: + df = pl.DataFrame({"a": [1.0]}) + # max precision is 38. + with pytest.raises(pl.exceptions.InvalidOperationError): + df.select(b=pl.col("a").cast(pl.Decimal(76, 38)))