MDEV-30255: fix trailing zeros from DISTINCT on decimals#4695
MDEV-30255: fix trailing zeros from DISTINCT on decimals#4695MooSayed1 wants to merge 1 commit intoMariaDB:10.11from
Conversation
1806d93 to
32d4918
Compare
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution. This is a preliminary review.
Please make sure you keep the single commit, but please add a commit message to it that is conformant to CODING_STANDARDS.md.
The rest of the change looks good to me, except one optional suggestion.
| UNION ALL | ||
| (SELECT '2'); | ||
|
|
||
| DROP TABLE t1; |
There was a problem hiding this comment.
Optional: We customarily add a comment to say "End of xx tests" for each version.
|
@gkodinov I thought I had followed the CODING_STANDARDS.md correctly, since the commit message length is within the allowed number of characters 47, and there’s an exception for the ticket number. |
32d4918 to
c0dcd57
Compare
gkodinov
left a comment
There was a problem hiding this comment.
LGTM. Thanks! Stand by for the final review.
There was a problem hiding this comment.
I checked how it works in different scenarios:
drop table if exists t;
create table t (c1 double);
insert into t values (0.1);
SELECT (c1 DIV 1)*0.1 FROM t; -- Returns 0.0
SELECT CAST((c1 DIV 1)*0.1 AS CHAR) FROM t; -- Returns 0.0
(SELECT (c1 DIV 1)*0.1 FROM t) UNION ALL (SELECT '1'); -- Returns 0
(SELECT DISTINCT (c1 DIV 1)*0.1 FROM t) UNION ALL (SELECT '1'); -- Returns 0.0
You're fixing the fourth query to return '0' instead of '0.0'.
But the correct change would be the other way around: fix the third query to return '0.0' instead of 0.
Please change your patch accordingly. Thanks.
6c7befa to
ada3c61
Compare
The expression (e.g. (c1 DIV 1)*0.1) has a declared precision of decimals=1. decimal_mul() strips trailing fractional zeros from the computed value -- for example 0*0.1 produces frac=0 -- so storing the value into a UNION VARCHAR column via Item::save_decimal_in_field() was producing "0" instead of the expected "0.0". The DISTINCT path was unaffected because it stores through Field_new_decimal::save_in_field(), which reads the field's own dec attribute and preserves the full precision. Fix: in Item::save_decimal_in_field(), after computing the value, restore frac to at least the item's declared decimals before calling field->store_decimal(). mysql-test/main/decimal_trailing_zeros.test,result: update expected results and comments to reflect the correct behaviour: both the plain and the DISTINCT variants of the UNION must show the same number of fractional digits.
ada3c61 to
6bdde34
Compare
The Jira issue number for this PR is: MDEV-30255
Description
In a non-DISTINCT
UNION ALL, a decimal expression like(c1 DIV 1)*0.1with
c1=0declaresdecimals=1(one fractional digit) but was showing"0"instead of"0.0".The DISTINCT path already produced the correct result; only the plain
UNION ALLpath was broken.The root cause is in
Item::save_decimal_in_field()insql/item.cc.Two arithmetic operations silently reduce a decimal's
fracattribute:decimal_mul()strips trailing fractional zeros —0 * 0.1producesfrac=0.decimal_div()callsdecimal_make_zero()for zero dividends, settingfrac=0and leaving the fractional buffer uninitialised.Field_longstr::store_decimal()formats the string usingdec->frac, sofrac=0→"0"instead of the expected"0.0".The fix: if the value's
fracis less than the expression's declareddecimals,call
round_to(decimals, TRUNCATE)before storing.round_to()is usedinstead of a bare
frac=assignment because it also zeroes the newly exposedfractional buffer words that
decimal_make_zero()leaves uninitialised.The extension is guarded to
decimals < DECIMAL_MAX_SCALE. Some items (e.g.Item_func_get_user_var) setdecimals = DECIMAL_MAX_SCALE (38)as a sentinelfor "unknown scale" and must not be extended.
Release Notes
UNION ALLon decimal expressions no longer strips trailing fractional zeros.For example,
(c1 DIV 1)*0.1withc1=0now correctly returns"0.0"instead of"0".How can this PR be tested?
Basing the PR against the correct MariaDB version
This is a bug fix. The earliest affected branch is 10.11, so this PR targets
upstream/10.11.PR quality check
How can this PR be tested?
The test creates an InnoDB table, runs the same decimal expression with and without
DISTINCT, and verifies the results are identical.Basing the PR against the correct MariaDB version
This is a bug fix targeting the 10.11 maintenance branch.
PR quality check