Skip to content

fix(mysql): decode DECIMAL columns into integer types correctly - #4422

Open
Map130 wants to merge 1 commit into
transact-rs:mainfrom
Map130:fix/mysql-decimal-integer-decode
Open

Map130 wants to merge 1 commit into
transact-rs:mainfrom
Map130:fix/mysql-decimal-integer-decode

Conversation

@Map130

@Map130 Map130 commented Sep 24, 2026

Copy link
Copy Markdown

Problem

Decoding a MySQL DECIMAL/NEWDECIMAL column into an integer type silently
corrupted the value. MySQL sends DECIMAL as ASCII text even in the binary
protocol, but the integer decoders read those bytes as a little-endian
integer, so decoding e.g. SUM(int_col) into u64 via an explicit type
override or try_get_unchecked produced garbage: the bytes b"13"
(0x31 0x33) decoded to 0x3331 = 13105 instead of 13.

Fix

int_decode/uint_decode now detect DECIMAL/NEWDECIMAL columns and parse
the textual value, requiring it to be integral:

  • integral DECIMAL → correct integer value;
  • fractional DECIMAL → a clean has a fractional part error instead of a
    silently corrupted result;
  • negative DECIMAL → decodes into signed integers, errors for unsigned.

Type::compatible is deliberately left unchanged, so macro inference still
maps DECIMAL columns to Decimal/BigDecimal and does not lossily infer
u64 for SUM().

Tests

Added decode_integer_from_decimal in tests/mysql/types.rs covering the
correct-value, fractional-error, and negative cases. Verified against a
live MySQL 8.0 with and without the rust_decimal/bigdecimal features;
existing mysql-types and mysql-macros suites pass.

…ectly

MySQL transmits DECIMAL/NEWDECIMAL as ASCII text even over the binary
protocol, but `int_decode`/`uint_decode` reinterpreted those bytes as a
little-endian integer. Decoding e.g. `SUM(int_col)` into `u64` via an
explicit type override or `try_get_unchecked` silently produced garbage
(the bytes `b"13"` were read as `0x3331` = 13105 instead of 13).

Parse the textual value for DECIMAL/NEWDECIMAL columns and require it to
be integral: integral values decode correctly, while fractional values
now return a clean error instead of a corrupted result.

The `Type::compatible` gate is intentionally left unchanged, so macro
type inference still resolves DECIMAL columns to `Decimal`/`BigDecimal`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Map130
Map130 marked this pull request as draft September 24, 2026 19:42
@Map130
Map130 marked this pull request as ready for review September 24, 2026 19:42
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.

1 participant