Skip to content

Fix DECFLOAT values with 16-31 decimal places (SignSpecialPlaces mask $2f -> $3f)#5

Open
mariuz wants to merge 1 commit into
MWASoftware:mainfrom
mariuz:fix-decfloat-places
Open

Fix DECFLOAT values with 16-31 decimal places (SignSpecialPlaces mask $2f -> $3f)#5
mariuz wants to merge 1 commit into
MWASoftware:mainfrom
mariuz:fix-decfloat-places

Conversation

@mariuz

@mariuz mariuz commented Jul 21, 2026

Copy link
Copy Markdown

Fixes #3.

TBCD.SignSpecialPlaces keeps the decimal-places count in bits 0..5 and the sign in bit 7, so the places mask must be $3f. Both DECFLOAT conversion paths in TFB30ClientAPI masked with $2f, dropping bit 4 — any value with 16..31 decimal places lost exactly 16 places (i.e. arrived multiplied by 10^16) on both the GetAsBCD read path (SQLDecFloatDecode) and the AsBCD parameter path (SQLDecFloatEncode). Values with 0..15 or 32..34 places were unaffected, which is how the bug stayed hidden.

The change is the two masks only (the third $2f in the file is inside a commented-out debug writeln and was left alone).

Verification (Firebird 6.0, LI-T6.0.0.2076, Linux aarch64, fpc 3.2.2): round trips at 8, 15, 16, 17, 22, 31 and 33 decimal places, decode via GetAsBCD+BCDToStr and encode via SQLParams[].AsBCD + server-side CAST(? AS VARCHAR(60)). Before: the 16/17/22/31-place cases all came back shifted (1.234567890123456712345678901234567). After: all fourteen round trips are exact, and the previously-correct cases are unchanged. Issue #3 has the full before/after table.

🤖 Generated with Claude Code

TBCD.SignSpecialPlaces keeps the number of decimal places in bits 0..5
(0..63) and the sign in bit 7, so the correct mask for the places field
is $3f.  SQLDecFloatEncode and SQLDecFloatDecode both masked with $2f,
which drops bit 4: any DECFLOAT value with 16..31 decimal places lost
exactly 16 places in both directions, i.e. was read back (and sent)
multiplied by 10^16.  Values with 0..15 or 32..34 places were unaffected,
which is why the bug could hide for so long.

Reproduced against Firebird 6.0 with round trips at 8, 15, 16, 17, 22,
31 and 33 decimal places: before the fix the 16, 17, 22 and 31 cases
came back as e.g. 1.2345678901234567 -> 12345678901234567 on both the
getAsBCD path and the SQLParams AsBCD path; after the fix all round
trips are exact.
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.

DECFLOAT values with 16-31 decimal places decode/encode with the decimal point off by 16 places (SignSpecialPlaces masked with $2f instead of $3f)

1 participant