From 161841854ddc4c2581b0a3714409f69359e19971 Mon Sep 17 00:00:00 2001 From: yu34po Date: Tue, 23 Oct 2018 11:47:26 +0800 Subject: [PATCH 1/4] builtin truncate function supprot unsignedint type and fix truncate int number use float64 transate maybe get approximate value --- expression/builtin_math.go | 46 ++++++++++++++++++++++++++++++--- expression/builtin_math_test.go | 3 +++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/expression/builtin_math.go b/expression/builtin_math.go index 04c59608d3bbd..74bba5e3b319c 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -110,6 +110,7 @@ var ( _ builtinFunc = &builtinTruncateIntSig{} _ builtinFunc = &builtinTruncateRealSig{} _ builtinFunc = &builtinTruncateDecimalSig{} + _ builtinFunc = &builtinTruncateUnintSig{} ) type absFunctionClass struct { @@ -1737,7 +1738,11 @@ func (c *truncateFunctionClass) getFunction(ctx sessionctx.Context, args []Expre var sig builtinFunc switch argTp { case types.ETInt: - sig = &builtinTruncateIntSig{bf} + if mysql.HasUnsignedFlag(args[0].GetType().Flag){ + sig = &builtinTruncateUnintSig{bf} + } else { + sig = &builtinTruncateIntSig{bf} + } case types.ETReal: sig = &builtinTruncateRealSig{bf} case types.ETDecimal: @@ -1826,6 +1831,41 @@ func (b *builtinTruncateIntSig) evalInt(row chunk.Row) (int64, bool, error) { return 0, isNull, errors.Trace(err) } - floatX := float64(x) - return int64(types.Truncate(floatX, int(d))), false, nil + if d >= 0 { + return x, false, nil + } else { + shift := int64(math.Pow10(int(-d))) + return x / shift * shift, false, nil + } +} + +func (b *builtinTruncateUnintSig) Clone() builtinFunc { + newSig := &builtinTruncateUnintSig{} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +type builtinTruncateUnintSig struct { + baseBuiltinFunc +} + +// evalInt evals a TRUNCATE(X,D). +// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate +func (b *builtinTruncateUnintSig) evalInt(row chunk.Row) (int64, bool, error) { + x, isNull, err := b.args[0].EvalInt(b.ctx, row) + if isNull || err != nil { + return 0, isNull, errors.Trace(err) + } + uintx := uint64(x) + + d, isNull, err := b.args[1].EvalInt(b.ctx, row) + if isNull || err != nil { + return 0, isNull, errors.Trace(err) + } + if d >= 0 { + return x, false, nil + } else { + shift := uint64(math.Pow10(int(-d))) + return int64(uintx / shift * shift), false, nil + } } diff --git a/expression/builtin_math_test.go b/expression/builtin_math_test.go index a0c291603a5c3..db01a7864dfe5 100644 --- a/expression/builtin_math_test.go +++ b/expression/builtin_math_test.go @@ -485,6 +485,9 @@ func (s *testEvaluatorSuite) TestTruncate(c *C) { {[]interface{}{newDec("23.298"), -100}, newDec("0")}, {[]interface{}{newDec("23.298"), 100}, newDec("23.298")}, {[]interface{}{nil, 2}, nil}, + {[]interface{}{uint64(9223372036854775808), -10}, 9223372030000000000}, + {[]interface{}{9223372036854775807, -7}, 9223372036850000000}, + {[]interface{}{uint64(18446744073709551615), -10}, uint64(18446744070000000000)}, } Dtbl := tblToDtbl(tbl) From 814ab32459e593bbeda1899a38270cf837c9b15a Mon Sep 17 00:00:00 2001 From: yu34po Date: Tue, 23 Oct 2018 13:26:51 +0800 Subject: [PATCH 2/4] file fmt and replace unint to uint --- expression/builtin_math.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/expression/builtin_math.go b/expression/builtin_math.go index 74bba5e3b319c..7e8cd8d1bedea 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -110,7 +110,7 @@ var ( _ builtinFunc = &builtinTruncateIntSig{} _ builtinFunc = &builtinTruncateRealSig{} _ builtinFunc = &builtinTruncateDecimalSig{} - _ builtinFunc = &builtinTruncateUnintSig{} + _ builtinFunc = &builtinTruncateUintSig{} ) type absFunctionClass struct { @@ -1738,8 +1738,8 @@ func (c *truncateFunctionClass) getFunction(ctx sessionctx.Context, args []Expre var sig builtinFunc switch argTp { case types.ETInt: - if mysql.HasUnsignedFlag(args[0].GetType().Flag){ - sig = &builtinTruncateUnintSig{bf} + if mysql.HasUnsignedFlag(args[0].GetType().Flag) { + sig = &builtinTruncateUintSig{bf} } else { sig = &builtinTruncateIntSig{bf} } @@ -1839,19 +1839,19 @@ func (b *builtinTruncateIntSig) evalInt(row chunk.Row) (int64, bool, error) { } } -func (b *builtinTruncateUnintSig) Clone() builtinFunc { - newSig := &builtinTruncateUnintSig{} +func (b *builtinTruncateUintSig) Clone() builtinFunc { + newSig := &builtinTruncateUintSig{} newSig.cloneFrom(&b.baseBuiltinFunc) return newSig } -type builtinTruncateUnintSig struct { +type builtinTruncateUintSig struct { baseBuiltinFunc } // evalInt evals a TRUNCATE(X,D). // See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate -func (b *builtinTruncateUnintSig) evalInt(row chunk.Row) (int64, bool, error) { +func (b *builtinTruncateUintSig) evalInt(row chunk.Row) (int64, bool, error) { x, isNull, err := b.args[0].EvalInt(b.ctx, row) if isNull || err != nil { return 0, isNull, errors.Trace(err) From df225ddda9b086f098c0b1e3807e8e4ad3208b06 Mon Sep 17 00:00:00 2001 From: yu34po Date: Tue, 23 Oct 2018 13:52:21 +0800 Subject: [PATCH 3/4] del else block for lint check --- expression/builtin_math.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/expression/builtin_math.go b/expression/builtin_math.go index 7e8cd8d1bedea..68ee63a974114 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -1833,10 +1833,9 @@ func (b *builtinTruncateIntSig) evalInt(row chunk.Row) (int64, bool, error) { if d >= 0 { return x, false, nil - } else { - shift := int64(math.Pow10(int(-d))) - return x / shift * shift, false, nil } + shift := int64(math.Pow10(int(-d))) + return x / shift * shift, false, nil } func (b *builtinTruncateUintSig) Clone() builtinFunc { @@ -1864,8 +1863,7 @@ func (b *builtinTruncateUintSig) evalInt(row chunk.Row) (int64, bool, error) { } if d >= 0 { return x, false, nil - } else { - shift := uint64(math.Pow10(int(-d))) - return int64(uintx / shift * shift), false, nil } + shift := uint64(math.Pow10(int(-d))) + return int64(uintx / shift * shift), false, nil } From e3a04a742bd9348941f2653fdef91774f9066cf4 Mon Sep 17 00:00:00 2001 From: yu34po Date: Tue, 23 Oct 2018 16:25:40 +0800 Subject: [PATCH 4/4] aaa integration test for truncate --- expression/integration_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/expression/integration_test.go b/expression/integration_test.go index c81203e1518b3..7ee4d4c4e26c0 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -477,6 +477,8 @@ func (s *testIntegrationSuite) TestMathBuiltin(c *C) { result.Check(testkit.Rows("100 123 123 120")) result = tk.MustQuery("SELECT truncate(123.456, -2), truncate(123.456, 2), truncate(123.456, 1), truncate(123.456, 3), truncate(1.23, 100), truncate(123456E-3, 2);") result.Check(testkit.Rows("100 123.45 123.4 123.456 1.230000000000000000000000000000 123.45")) + result = tk.MustQuery("SELECT truncate(9223372036854775807, -7), truncate(9223372036854775808, -10), truncate(cast(-1 as unsigned), -10);") + result.Check(testkit.Rows("9223372036850000000 9223372030000000000 18446744070000000000")) tk.MustExec(`drop table if exists t;`) tk.MustExec(`create table t(a date, b datetime, c timestamp, d varchar(20));`)