Skip to content

fix(arrow/compute): accept type max value in safe decimal-to-int cast#862

Merged
zeroshade merged 1 commit into
apache:mainfrom
zeroshade:fix/decimal-int-cast-maxint64
Jun 23, 2026
Merged

fix(arrow/compute): accept type max value in safe decimal-to-int cast#862
zeroshade merged 1 commit into
apache:mainfrom
zeroshade:fix/decimal-int-cast-maxint64

Conversation

@zeroshade

Copy link
Copy Markdown
Member

Rationale for this change

The safe decimal128/decimal256 → integer cast kernel range-checks each value against the output type's bounds before truncating to the low 64 bits. The upper-bound check used value >= max, where max is the inclusive maximum of the output integer type (e.g. math.MaxInt64 for int64, computed via MaxOf[T]()). As a result a value exactly equal to the type maximum was incorrectly rejected as "integer value out of bounds", even though it is a valid in-range value. This affects every integer output type (int8/int16/int32/int64 and the unsigned variants), not just int64.

This was noticed while working around the behavior downstream in the ADBC Snowflake driver (adbc-drivers/snowflake#161), where it was suggested to fix it upstream here.

What changes are included in this PR?

  • In decimalToIntImpl (arrow/compute/internal/kernels/numeric_cast.go), change the upper-bound overflow check from value >= max to value > max so the inclusive maximum is accepted, matching the already-inclusive lower-bound check (value < min). The decimal[T] helper interface now requires Greater instead of GreaterEqual; both decimal128.Num and decimal256.Num already implement it.

Are these changes tested?

Yes. Added an int64 bounds inclusive regression subtest to TestDecimal128ToInt and TestDecimal256ToInt that assert, with AllowIntOverflow=false:

  • math.MaxInt64 (9223372036854775807) and math.MinInt64 (-9223372036854775808) cast successfully, and
  • values one beyond either bound still fail as overflow.

go test ./arrow/compute/... passes and go vet is clean.

Are there any user-facing changes?

Yes — a bug fix. A safe (non-AllowIntOverflow) decimal→integer cast of a value equal to the destination type's maximum (e.g. math.MaxInt64) now succeeds instead of returning an ErrInvalid "integer value out of bounds" error. Values genuinely outside the range still error as before.

The safe decimal->integer cast kernel checked `value >= max`, where max is
the inclusive maximum of the output integer type (e.g. math.MaxInt64). This
rejected the maximum value itself as out of bounds for every integer output
type, even though it is a valid in-range value. Use a strict `value > max`
check so the inclusive upper bound is accepted, matching the already
inclusive lower bound.

Adds boundary regression tests covering math.MinInt64/math.MaxInt64 for both
decimal128 and decimal256 inputs.
@zeroshade
zeroshade requested review from amoeba, kou and lidavidm June 23, 2026 16:35
@zeroshade
zeroshade merged commit d17f687 into apache:main Jun 23, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants