Skip to content

Spurious failure when casting long strings to decimal #10664

Description

@neilconway

Describe the bug

Casting a string to a decimal type fails if the input has more than ~76 fractional digits. This is suboptimal, because digits beyond the target scale only matter for rounding, and the correct result is easily representable in the target type.

To Reproduce

use arrow_array::{cast::AsArray, types::Decimal128Type, StringArray};
use arrow_cast::{cast_with_options, CastOptions};
use arrow_schema::DataType;
use std::sync::Arc;

fn main() {
    // 0.111... with 80 fractional digits; at scale 4 this is exactly 0.1111
    let input = format!("0.{}", "1".repeat(80));
    let array = Arc::new(StringArray::from(vec![input])) as arrow_array::ArrayRef;
    let options = CastOptions { safe: false, ..Default::default() };
    let result = cast_with_options(&array, &DataType::Decimal128(38, 4), &options);
    println!("{result:?}");
}

Result

Err(CastError("Cannot cast string '0.11111...11111' to value of Decimal128(38, 10) type"))

Expected behavior

This should succeed and print 0.1111, following the rounding behavior we use for shorter inputs.

Additional context

No response

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions