-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
expression/types: fix decimal minus/round/multiple result #7001
Conversation
server/util.go
Outdated
@@ -254,7 +254,7 @@ func dumpBinaryRow(buffer []byte, columns []*ColumnInfo, row types.Row) ([]byte, | |||
case mysql.TypeDouble: | |||
buffer = dumpUint64(buffer, math.Float64bits(row.GetFloat64(i))) | |||
case mysql.TypeNewDecimal: | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(row.GetMyDecimal(i).String())) | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(string(row.GetMyDecimal(i).ToString()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why change this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mmm...In MySQL this sql will not round up to zero....
select -0.0000000000000000000000000000000000000000000000000017382578996420603
so I try to run test case ahead in here to see what happen if we
don't truncate it- -
types/mydecimal.go
Outdated
if from.IsZero() { | ||
return &to | ||
} | ||
if from.IsNegative() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about to.negative = !from.negative
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done~
server/util.go
Outdated
@@ -254,7 +254,7 @@ func dumpBinaryRow(buffer []byte, columns []*ColumnInfo, row types.Row) ([]byte, | |||
case mysql.TypeDouble: | |||
buffer = dumpUint64(buffer, math.Float64bits(row.GetFloat64(i))) | |||
case mysql.TypeNewDecimal: | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(row.GetMyDecimal(i).String())) | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(string(row.GetMyDecimal(i).ToString()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
buffer = dumpLengthEncodedString(buffer, row.GetMyDecimal(i).ToString())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea~finally we revert it and use continue call round up.- -
server/util.go
Outdated
@@ -312,7 +312,7 @@ func dumpTextRow(buffer []byte, columns []*ColumnInfo, row types.Row) ([]byte, e | |||
tmp = appendFormatFloat(tmp[:0], row.GetFloat64(i), prec, 64) | |||
buffer = dumpLengthEncodedString(buffer, tmp) | |||
case mysql.TypeNewDecimal: | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(row.GetMyDecimal(i).String())) | |||
buffer = dumpLengthEncodedString(buffer, hack.Slice(string(row.GetMyDecimal(i).ToString()))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
@@ -1768,7 +1769,7 @@ func (b *builtinTruncateDecimalSig) evalDecimal(row types.Row) (*types.MyDecimal | |||
} | |||
|
|||
result := new(types.MyDecimal) | |||
if err := x.Round(result, int(d), types.ModeTruncate); err != nil { | |||
if err := x.Round(result, mathutil.Min(int(d), b.getRetTp().Decimal), types.ModeTruncate); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Truncate's param is given by user, so need check dec < tp.Decimal(which is less than MAX_DECIMAL_SCALE)
e.g. Truncate(1.124, 100)
(we had test case).
@@ -713,9 +713,6 @@ func (d *MyDecimal) doMiniRightShift(shift, beg, end int) { | |||
// RETURN VALUE | |||
// eDecOK/eDecTruncated | |||
func (d *MyDecimal) Round(to *MyDecimal, frac int, roundMode RoundMode) (err error) { | |||
if frac > mysql.MaxDecimalScale { | |||
frac = mysql.MaxDecimalScale | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move this check out of mydecimal, and not > mysql.MaxDecimalScale
but > e.tp.Decimals
@@ -523,7 +524,7 @@ func (s *builtinArithmeticMultiplyDecimalSig) evalDecimal(row types.Row) (*types | |||
} | |||
c := &types.MyDecimal{} | |||
err = types.DecimalMul(a, b, c) | |||
if err != nil { | |||
if err != nil && !terror.ErrorEqual(err, types.ErrTruncated) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conventions:
decimal_smth() <= 1 -- result is usable, but precision loss is possible
In MySQL multiple will ignore mul DataTruncated error without any error or warning.....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have some test to cover this behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes~ 0151f10 add a new case, today.
select 2.00000000000000000000000000000001 * 1.000000000000000000000000000000000000000000002
will failed in master, but pass in this PR and mysql with 2.000000000000000000000000000000
/run-all-tests tidb-test=pr/545 |
/run-unit-test tidb-test=pr/545 |
PTAL @coocood @AndreMouche if free~ thx |
types/mydecimal_test.go
Outdated
@@ -626,7 +645,7 @@ func (s *testMyDecimalSuite) TestMul(c *C) { | |||
{"123456", "987654321", "121931851853376", nil}, | |||
{"123456", "9876543210", "1219318518533760", nil}, | |||
{"123", "0.01", "1.23", nil}, | |||
{"123", "0", "0", nil}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove the old test case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's my mistake.- -
In detail fix two question: - minus sign direct change decimal's negative property - write decimal's round no longer truncate scale param any more fixes #6997
LGTM |
PTAL @AndreMouche @XuHuaiyu if free, thx~ |
expression/builtin_math.go
Outdated
@@ -292,6 +295,25 @@ func (c *roundFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi | |||
return sig, nil | |||
} | |||
|
|||
// fixDecimal4RoundAndTruncate fixes tp.decimals of round/truncate func. | |||
func fixDecimal4RoundAndTruncate(ctx sessionctx.Context, args []Expression, retType types.EvalType) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/fix.../calc.../
expression/builtin_math.go
Outdated
return args[0].GetType().Decimal | ||
} | ||
argDec, isNull, err := secondConst.EvalInt(ctx, nil) | ||
if isNull || err != nil || argDec < 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should check err
firstly
/run-all-tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
What have you changed? (mandatory)
this PR mainly fix three questions:
-x
) direct change decimal's negative property. (relate to negative small decimal return unexcept result #6997)decimal.round
base on the result of expression's decimal type inferdecimal.round
expression's decimals type infer which help 2nd fixfixes #6997, #6985
What are the type of the changes (mandatory)?
The currently defined types are listed below, please pick one of the types for this PR by removing the others:
How has this PR been tested (mandatory)?
This change is