Skip to content
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

Merged
merged 9 commits into from
Jul 11, 2018
Merged

expression/types: fix decimal minus/round/multiple result #7001

merged 9 commits into from
Jul 11, 2018

Conversation

lysu
Copy link
Contributor

@lysu lysu commented Jul 5, 2018

What have you changed? (mandatory)

this PR mainly fix three questions:

fixes #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:

  • Bug fix (non-breaking change which fixes an issue)

How has this PR been tested (mandatory)?

  • unit tests
  • integration tests(pingcap/tidb-test#545)

This change is Reviewable

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())))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this?

Copy link
Contributor Author

@lysu lysu Jul 5, 2018

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- -

@lysu lysu added the status/DNM label Jul 5, 2018
if from.IsZero() {
return &to
}
if from.IsNegative() {
Copy link
Member

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?

Copy link
Contributor Author

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())))
Copy link
Contributor

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())

Copy link
Contributor Author

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())))
Copy link
Contributor

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 {
Copy link
Contributor Author

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
}
Copy link
Contributor Author

@lysu lysu Jul 6, 2018

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) {
Copy link
Contributor Author

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.....

Copy link
Member

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?

Copy link
Contributor Author

@lysu lysu Jul 11, 2018

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

@lysu
Copy link
Contributor Author

lysu commented Jul 7, 2018

/run-all-tests tidb-test=pr/545

@lysu lysu removed the status/DNM label Jul 7, 2018
@lysu lysu changed the title expression/types: fix negative small decimal bug. expression/types: fix decimal minus/round/multiple result Jul 7, 2018
@lysu
Copy link
Contributor Author

lysu commented Jul 7, 2018

/run-unit-test tidb-test=pr/545

@lysu
Copy link
Contributor Author

lysu commented Jul 8, 2018

PTAL @coocood @AndreMouche if free~ thx

@@ -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},
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's my mistake.- -

@coocood
Copy link
Member

coocood commented Jul 10, 2018

LGTM

@coocood coocood added the status/LGT1 Indicates that a PR has LGTM 1. label Jul 10, 2018
@lysu
Copy link
Contributor Author

lysu commented Jul 10, 2018

PTAL @AndreMouche @XuHuaiyu if free, thx~

@zz-jason zz-jason self-assigned this Jul 11, 2018
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/fix.../calc.../

return args[0].GetType().Decimal
}
argDec, isNull, err := secondConst.EvalInt(ctx, nil)
if isNull || err != nil || argDec < 0 {
Copy link
Member

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

@zz-jason
Copy link
Member

/run-all-tests

Copy link
Member

@zz-jason zz-jason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@zz-jason zz-jason added status/LGT2 Indicates that a PR has LGTM 2. component/expression and removed status/LGT1 Indicates that a PR has LGTM 1. labels Jul 11, 2018
@zz-jason zz-jason merged commit 5f7fc80 into pingcap:master Jul 11, 2018
@lysu lysu deleted the dev-decimal-mul-fix branch July 12, 2018 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

negative small decimal return unexcept result
5 participants