Skip to content

Casting decimal -> decimal with large scale is buggy #10946

Description

@neilconway

Describe the bug

Casting decimal -> decimal with a much larger scale can produce incorrect values, including panics in debug mode.

To Reproduce

use arrow_array::{Array, Decimal256Array};
use arrow_buffer::i256;
use arrow_cast::{cast_with_options, CastOptions};
use arrow_schema::DataType;

let array = Decimal256Array::from(vec![
    i256::from_i128(1),
    i256::from_i128(10_i128.pow(16)),
    i256::from_i128(10_i128.pow(17)),
])
.with_precision_and_scale(76, 0)
.unwrap();

// Strict mode; safe mode returns the same values (no nulls, no error)
let options = CastOptions { safe: false, ..Default::default() };
let result = cast_with_options(&array, &DataType::Decimal256(76, 60), &options).unwrap();

Results:

1                  -> 1000000000000000000000000000000000000000000000000000000000000
10000000000000000  -> 10000000000000000000000000000000000000000000000000000000000000000000000000000
100000000000000000 -> -15792089237316195423570985008687907853269984665640564039457584007913129639936

The first result is correct.

The second result exceeds the maximum value representable at precision 76 but is returned without error.

The third result is just wrong.

Expected behavior

No response

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