Skip to content

Commit

Permalink
expression: add warnings for logarithm functions (#18668) (#19291)
Browse files Browse the repository at this point in the history
Signed-off-by: ti-srebot <ti-srebot@pingcap.com>
  • Loading branch information
ti-srebot authored Sep 1, 2020
1 parent 1716cdf commit e190796
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 69 deletions.
1 change: 1 addition & 0 deletions errno/errcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,7 @@ const (
ErrErrorLast = 1863
ErrMaxExecTimeExceeded = 1907
ErrInvalidFieldSize = 3013
ErrInvalidArgumentForLogarithm = 3020
ErrIncorrectType = 3064
ErrInvalidJSONData = 3069
ErrGeneratedColumnFunctionIsNotAllowed = 3102
Expand Down
1 change: 1 addition & 0 deletions errno/errname.go
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,7 @@ var MySQLErrName = map[uint16]string{
ErrGeneratedColumnRefAutoInc: "Generated column '%s' cannot refer to auto-increment column.",
ErrWarnConflictingHint: "Hint %s is ignored as conflicting/duplicated.",
ErrInvalidFieldSize: "Invalid size for column '%s'.",
ErrInvalidArgumentForLogarithm: "Invalid argument for logarithm",
ErrIncorrectType: "Incorrect type for argument %s in function %s.",
ErrInvalidJSONData: "Invalid JSON data provided to function %s: %s",
ErrInvalidJSONText: "Invalid JSON text: %-.192s",
Expand Down
4 changes: 4 additions & 0 deletions expression/builtin_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,7 @@ func (b *builtinLog1ArgSig) evalReal(row chunk.Row) (float64, bool, error) {
return 0, isNull, err
}
if val <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
return 0, true, nil
}
return math.Log(val), false, nil
Expand Down Expand Up @@ -897,6 +898,7 @@ func (b *builtinLog2ArgsSig) evalReal(row chunk.Row) (float64, bool, error) {
}

if val1 <= 0 || val1 == 1 || val2 <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
return 0, true, nil
}

Expand Down Expand Up @@ -938,6 +940,7 @@ func (b *builtinLog2Sig) evalReal(row chunk.Row) (float64, bool, error) {
return 0, isNull, err
}
if val <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
return 0, true, nil
}
return math.Log2(val), false, nil
Expand Down Expand Up @@ -978,6 +981,7 @@ func (b *builtinLog10Sig) evalReal(row chunk.Row) (float64, bool, error) {
return 0, isNull, err
}
if val <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
return 0, true, nil
}
return math.Log10(val), false, nil
Expand Down
120 changes: 59 additions & 61 deletions expression/builtin_math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,21 +238,23 @@ func (s *testEvaluatorSuite) TestFloor(c *C) {

func (s *testEvaluatorSuite) TestLog(c *C) {
tests := []struct {
args []interface{}
expect float64
isNil bool
getWarning bool
args []interface{}
expect float64
isNil bool
warningCount uint16
}{
{[]interface{}{nil}, 0, true, false},
{[]interface{}{nil, nil}, 0, true, false},
{[]interface{}{int64(100)}, 4.605170185988092, false, false},
{[]interface{}{float64(100)}, 4.605170185988092, false, false},
{[]interface{}{int64(10), int64(100)}, 2, false, false},
{[]interface{}{float64(10), float64(100)}, 2, false, false},
{[]interface{}{float64(-1)}, 0, true, false},
{[]interface{}{float64(1), float64(2)}, 0, true, false},
{[]interface{}{float64(0.5), float64(0.25)}, 2, false, false},
{[]interface{}{"abc"}, 0, false, true},
{[]interface{}{nil}, 0, true, 0},
{[]interface{}{nil, nil}, 0, true, 0},
{[]interface{}{int64(100)}, 4.605170185988092, false, 0},
{[]interface{}{float64(100)}, 4.605170185988092, false, 0},
{[]interface{}{int64(10), int64(100)}, 2, false, 0},
{[]interface{}{float64(10), float64(100)}, 2, false, 0},
{[]interface{}{float64(-1)}, 0, true, 1},
{[]interface{}{float64(2), float64(-1)}, 0, true, 1},
{[]interface{}{float64(-1), float64(2)}, 0, true, 1},
{[]interface{}{float64(1), float64(2)}, 0, true, 1},
{[]interface{}{float64(0.5), float64(0.25)}, 2, false, 0},
{[]interface{}{"abc"}, 0, true, 2},
}

for _, test := range tests {
Expand All @@ -261,16 +263,14 @@ func (s *testEvaluatorSuite) TestLog(c *C) {
c.Assert(err, IsNil)

result, err := f.Eval(chunk.Row{})
if test.getWarning {
c.Assert(err, IsNil)
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+1)
c.Assert(err, IsNil)
if test.warningCount > 0 {
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+test.warningCount)
}
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(err, IsNil)
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(result.GetFloat64(), Equals, test.expect)
}
c.Assert(result.GetFloat64(), Equals, test.expect)
}
}

Expand All @@ -280,17 +280,18 @@ func (s *testEvaluatorSuite) TestLog(c *C) {

func (s *testEvaluatorSuite) TestLog2(c *C) {
tests := []struct {
args interface{}
expect float64
isNil bool
getWarning bool
args interface{}
expect float64
isNil bool
warningCount uint16
}{
{nil, 0, true, false},
{int64(16), 4, false, false},
{float64(16), 4, false, false},
{int64(5), 2.321928094887362, false, false},
{int64(-1), 0, true, false},
{"4abc", 0, false, true},
{nil, 0, true, 0},
{int64(16), 4, false, 0},
{float64(16), 4, false, 0},
{int64(5), 2.321928094887362, false, 0},
{int64(-1), 0, true, 1},
{"4abc", 2, false, 1},
{"abc", 0, true, 2},
}

for _, test := range tests {
Expand All @@ -299,16 +300,14 @@ func (s *testEvaluatorSuite) TestLog2(c *C) {
c.Assert(err, IsNil)

result, err := f.Eval(chunk.Row{})
if test.getWarning {
c.Assert(err, IsNil)
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+1)
c.Assert(err, IsNil)
if test.warningCount > 0 {
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+test.warningCount)
}
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(err, IsNil)
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(result.GetFloat64(), Equals, test.expect)
}
c.Assert(result.GetFloat64(), Equals, test.expect)
}
}

Expand All @@ -318,17 +317,18 @@ func (s *testEvaluatorSuite) TestLog2(c *C) {

func (s *testEvaluatorSuite) TestLog10(c *C) {
tests := []struct {
args interface{}
expect float64
isNil bool
getWarning bool
args interface{}
expect float64
isNil bool
warningCount uint16
}{
{nil, 0, true, false},
{int64(100), 2, false, false},
{float64(100), 2, false, false},
{int64(101), 2.0043213737826426, false, false},
{int64(-1), 0, true, false},
{"100abc", 0, false, true},
{nil, 0, true, 0},
{int64(100), 2, false, 0},
{float64(100), 2, false, 0},
{int64(101), 2.0043213737826426, false, 0},
{int64(-1), 0, true, 1},
{"100abc", 2, false, 1},
{"abc", 0, true, 2},
}

for _, test := range tests {
Expand All @@ -337,16 +337,14 @@ func (s *testEvaluatorSuite) TestLog10(c *C) {
c.Assert(err, IsNil)

result, err := f.Eval(chunk.Row{})
if test.getWarning {
c.Assert(err, IsNil)
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+1)
c.Assert(err, IsNil)
if test.warningCount > 0 {
c.Assert(s.ctx.GetSessionVars().StmtCtx.WarningCount(), Equals, preWarningCnt+test.warningCount)
}
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(err, IsNil)
if test.isNil {
c.Assert(result.Kind(), Equals, types.KindNull)
} else {
c.Assert(result.GetFloat64(), Equals, test.expect)
}
c.Assert(result.GetFloat64(), Equals, test.expect)
}
}

Expand Down
4 changes: 4 additions & 0 deletions expression/builtin_math_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func (b *builtinLog1ArgSig) vecEvalReal(input *chunk.Chunk, result *chunk.Column
continue
}
if f64s[i] <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
result.SetNull(i, true)
} else {
f64s[i] = math.Log(f64s[i])
Expand All @@ -57,6 +58,7 @@ func (b *builtinLog2Sig) vecEvalReal(input *chunk.Chunk, result *chunk.Column) e
continue
}
if f64s[i] <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
result.SetNull(i, true)
} else {
f64s[i] = math.Log2(f64s[i])
Expand All @@ -79,6 +81,7 @@ func (b *builtinLog10Sig) vecEvalReal(input *chunk.Chunk, result *chunk.Column)
continue
}
if f64s[i] <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
result.SetNull(i, true)
} else {
f64s[i] = math.Log10(f64s[i])
Expand Down Expand Up @@ -474,6 +477,7 @@ func (b *builtinLog2ArgsSig) vecEvalReal(input *chunk.Chunk, result *chunk.Colum
continue
}
if d[i] <= 0 || d[i] == 1 || x[i] <= 0 {
b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInvalidArgumentForLogarithm)
result.SetNull(i, true)
}
d[i] = math.Log(x[i]) / math.Log(d[i])
Expand Down
17 changes: 9 additions & 8 deletions expression/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,23 @@
package expression

import (
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/terror"
mysql "github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/types"
)

// Error instances.
var (
// All the exported errors are defined here:
ErrIncorrectParameterCount = terror.ClassExpression.New(mysql.ErrWrongParamcountToNativeFct, mysql.MySQLErrName[mysql.ErrWrongParamcountToNativeFct])
ErrDivisionByZero = terror.ClassExpression.New(mysql.ErrDivisionByZero, mysql.MySQLErrName[mysql.ErrDivisionByZero])
ErrRegexp = terror.ClassExpression.New(mysql.ErrRegexp, mysql.MySQLErrName[mysql.ErrRegexp])
ErrOperandColumns = terror.ClassExpression.New(mysql.ErrOperandColumns, mysql.MySQLErrName[mysql.ErrOperandColumns])
ErrCutValueGroupConcat = terror.ClassExpression.New(mysql.ErrCutValueGroupConcat, mysql.MySQLErrName[mysql.ErrCutValueGroupConcat])
ErrFunctionsNoopImpl = terror.ClassExpression.New(mysql.ErrNotSupportedYet, "function %s has only noop implementation in tidb now, use tidb_enable_noop_functions to enable these functions")
ErrIncorrectType = terror.ClassExpression.New(mysql.ErrIncorrectType, mysql.MySQLErrName[mysql.ErrIncorrectType])
ErrIncorrectParameterCount = terror.ClassExpression.New(mysql.ErrWrongParamcountToNativeFct, mysql.MySQLErrName[mysql.ErrWrongParamcountToNativeFct])
ErrDivisionByZero = terror.ClassExpression.New(mysql.ErrDivisionByZero, mysql.MySQLErrName[mysql.ErrDivisionByZero])
ErrRegexp = terror.ClassExpression.New(mysql.ErrRegexp, mysql.MySQLErrName[mysql.ErrRegexp])
ErrOperandColumns = terror.ClassExpression.New(mysql.ErrOperandColumns, mysql.MySQLErrName[mysql.ErrOperandColumns])
ErrCutValueGroupConcat = terror.ClassExpression.New(mysql.ErrCutValueGroupConcat, mysql.MySQLErrName[mysql.ErrCutValueGroupConcat])
ErrFunctionsNoopImpl = terror.ClassExpression.New(mysql.ErrNotSupportedYet, "function %s has only noop implementation in tidb now, use tidb_enable_noop_functions to enable these functions")
ErrInvalidArgumentForLogarithm = terror.ClassExpression.New(mysql.ErrInvalidArgumentForLogarithm, mysql.MySQLErrName[mysql.ErrInvalidArgumentForLogarithm])
ErrIncorrectType = terror.ClassExpression.New(mysql.ErrIncorrectType, mysql.MySQLErrName[mysql.ErrIncorrectType])

// All the un-exported errors are defined here:
errFunctionNotExists = terror.ClassExpression.New(mysql.ErrSpDoesNotExist, mysql.MySQLErrName[mysql.ErrSpDoesNotExist])
Expand Down

0 comments on commit e190796

Please sign in to comment.