github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/evaluator/evaluator_test.go (about)

     1  // Copyright 2015 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package evaluator
    15  
    16  import (
    17  	"testing"
    18  	"time"
    19  
    20  	"fmt"
    21  	. "github.com/insionng/yougam/libraries/pingcap/check"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    24  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/parser"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/parser/opcode"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/sessionctx/variable"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/charset"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/mock"
    30  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak"
    31  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testutil"
    32  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    33  )
    34  
    35  var _ = Suite(&testEvaluatorSuite{})
    36  
    37  func TestT(t *testing.T) {
    38  	TestingT(t)
    39  }
    40  
    41  type testEvaluatorSuite struct {
    42  }
    43  
    44  func parseExpr(c *C, expr string) ast.ExprNode {
    45  	s, err := parser.ParseOneStmt("select "+expr, "", "")
    46  	c.Assert(err, IsNil)
    47  	stmt := s.(*ast.SelectStmt)
    48  	return stmt.Fields.Fields[0].Expr
    49  }
    50  
    51  type testCase struct {
    52  	exprStr   string
    53  	resultStr string
    54  }
    55  
    56  func (s *testEvaluatorSuite) runTests(c *C, cases []testCase) {
    57  	ctx := mock.NewContext()
    58  	for _, ca := range cases {
    59  		expr := parseExpr(c, ca.exprStr)
    60  		val, err := Eval(ctx, expr)
    61  		c.Assert(err, IsNil)
    62  		valStr := fmt.Sprintf("%v", val.GetValue())
    63  		c.Assert(valStr, Equals, ca.resultStr, Commentf("for %s", ca.exprStr))
    64  	}
    65  }
    66  
    67  func (s *testEvaluatorSuite) TestBetween(c *C) {
    68  	defer testleak.AfterTest(c)()
    69  	cases := []testCase{
    70  		{exprStr: "1 between 2 and 3", resultStr: "0"},
    71  		{exprStr: "1 not between 2 and 3", resultStr: "1"},
    72  	}
    73  	s.runTests(c, cases)
    74  }
    75  
    76  func (s *testEvaluatorSuite) TestBinopComparison(c *C) {
    77  	defer testleak.AfterTest(c)()
    78  	ctx := mock.NewContext()
    79  	tbl := []struct {
    80  		lhs    interface{}
    81  		op     opcode.Op
    82  		rhs    interface{}
    83  		result int64 // 0 for false, 1 for true
    84  	}{
    85  		// test EQ
    86  		{1, opcode.EQ, 2, 0},
    87  		{false, opcode.EQ, false, 1},
    88  		{false, opcode.EQ, true, 0},
    89  		{true, opcode.EQ, true, 1},
    90  		{true, opcode.EQ, false, 0},
    91  		{"1", opcode.EQ, true, 1},
    92  		{"1", opcode.EQ, false, 0},
    93  
    94  		// test NEQ
    95  		{1, opcode.NE, 2, 1},
    96  		{false, opcode.NE, false, 0},
    97  		{false, opcode.NE, true, 1},
    98  		{true, opcode.NE, true, 0},
    99  		{"1", opcode.NE, true, 0},
   100  		{"1", opcode.NE, false, 1},
   101  
   102  		// test GT, GE
   103  		{1, opcode.GT, 0, 1},
   104  		{1, opcode.GT, 1, 0},
   105  		{1, opcode.GE, 1, 1},
   106  		{3.14, opcode.GT, 3, 1},
   107  		{3.14, opcode.GE, 3.14, 1},
   108  
   109  		// test LT, LE
   110  		{1, opcode.LT, 2, 1},
   111  		{1, opcode.LT, 1, 0},
   112  		{1, opcode.LE, 1, 1},
   113  	}
   114  	for _, t := range tbl {
   115  		expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)}
   116  		v, err := Eval(ctx, expr)
   117  		c.Assert(err, IsNil)
   118  		val, err := v.ToBool()
   119  		c.Assert(err, IsNil)
   120  		c.Assert(val, Equals, t.result)
   121  	}
   122  
   123  	// test nil
   124  	nilTbl := []struct {
   125  		lhs interface{}
   126  		op  opcode.Op
   127  		rhs interface{}
   128  	}{
   129  		{nil, opcode.EQ, nil},
   130  		{nil, opcode.EQ, 1},
   131  		{nil, opcode.NE, nil},
   132  		{nil, opcode.NE, 1},
   133  		{nil, opcode.LT, nil},
   134  		{nil, opcode.LT, 1},
   135  		{nil, opcode.LE, nil},
   136  		{nil, opcode.LE, 1},
   137  		{nil, opcode.GT, nil},
   138  		{nil, opcode.GT, 1},
   139  		{nil, opcode.GE, nil},
   140  		{nil, opcode.GE, 1},
   141  	}
   142  
   143  	for _, t := range nilTbl {
   144  		expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)}
   145  		v, err := Eval(ctx, expr)
   146  		c.Assert(err, IsNil)
   147  		c.Assert(v.Kind(), Equals, types.KindNull)
   148  	}
   149  }
   150  
   151  func (s *testEvaluatorSuite) TestBinopLogic(c *C) {
   152  	defer testleak.AfterTest(c)()
   153  	ctx := mock.NewContext()
   154  	tbl := []struct {
   155  		lhs interface{}
   156  		op  opcode.Op
   157  		rhs interface{}
   158  		ret interface{}
   159  	}{
   160  		{nil, opcode.AndAnd, 1, nil},
   161  		{nil, opcode.AndAnd, 0, 0},
   162  		{nil, opcode.OrOr, 1, 1},
   163  		{nil, opcode.OrOr, 0, nil},
   164  		{nil, opcode.LogicXor, 1, nil},
   165  		{nil, opcode.LogicXor, 0, nil},
   166  		{1, opcode.AndAnd, 0, 0},
   167  		{1, opcode.AndAnd, 1, 1},
   168  		{1, opcode.OrOr, 0, 1},
   169  		{1, opcode.OrOr, 1, 1},
   170  		{0, opcode.OrOr, 0, 0},
   171  		{1, opcode.LogicXor, 0, 1},
   172  		{1, opcode.LogicXor, 1, 0},
   173  		{0, opcode.LogicXor, 0, 0},
   174  		{0, opcode.LogicXor, 1, 1},
   175  	}
   176  	for _, t := range tbl {
   177  		expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)}
   178  		v, err := Eval(ctx, expr)
   179  		c.Assert(err, IsNil)
   180  		switch x := t.ret.(type) {
   181  		case nil:
   182  			c.Assert(v.Kind(), Equals, types.KindNull)
   183  		case int:
   184  			c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(x)))
   185  		}
   186  	}
   187  }
   188  
   189  func (s *testEvaluatorSuite) TestBinopBitop(c *C) {
   190  	defer testleak.AfterTest(c)()
   191  	ctx := mock.NewContext()
   192  	tbl := []struct {
   193  		lhs interface{}
   194  		op  opcode.Op
   195  		rhs interface{}
   196  		ret interface{}
   197  	}{
   198  		{1, opcode.And, 1, 1},
   199  		{1, opcode.Or, 1, 1},
   200  		{1, opcode.Xor, 1, 0},
   201  		{1, opcode.LeftShift, 1, 2},
   202  		{2, opcode.RightShift, 1, 1},
   203  		{nil, opcode.And, 1, nil},
   204  		{1, opcode.And, nil, nil},
   205  		{nil, opcode.Or, 1, nil},
   206  		{nil, opcode.Xor, 1, nil},
   207  		{nil, opcode.LeftShift, 1, nil},
   208  		{nil, opcode.RightShift, 1, nil},
   209  	}
   210  
   211  	for _, t := range tbl {
   212  		expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)}
   213  		v, err := Eval(ctx, expr)
   214  		c.Assert(err, IsNil)
   215  
   216  		switch x := t.ret.(type) {
   217  		case nil:
   218  			c.Assert(v.Kind(), Equals, types.KindNull)
   219  		case int:
   220  			c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(x)))
   221  		}
   222  	}
   223  }
   224  
   225  func (s *testEvaluatorSuite) TestBinopNumeric(c *C) {
   226  	defer testleak.AfterTest(c)()
   227  	ctx := mock.NewContext()
   228  	tbl := []struct {
   229  		lhs interface{}
   230  		op  opcode.Op
   231  		rhs interface{}
   232  		ret interface{}
   233  	}{
   234  		// plus
   235  		{1, opcode.Plus, 1, 2},
   236  		{1, opcode.Plus, uint64(1), 2},
   237  		{1, opcode.Plus, "1", 2},
   238  		{1, opcode.Plus, mysql.NewDecimalFromInt(1, 0), 2},
   239  		{uint64(1), opcode.Plus, 1, 2},
   240  		{uint64(1), opcode.Plus, uint64(1), 2},
   241  		{1, opcode.Plus, []byte("1"), 2},
   242  		{1, opcode.Plus, mysql.Hex{Value: 1}, 2},
   243  		{1, opcode.Plus, mysql.Bit{Value: 1, Width: 1}, 2},
   244  		{1, opcode.Plus, mysql.Enum{Name: "a", Value: 1}, 2},
   245  		{1, opcode.Plus, mysql.Set{Name: "a", Value: 1}, 2},
   246  
   247  		// minus
   248  		{1, opcode.Minus, 1, 0},
   249  		{1, opcode.Minus, uint64(1), 0},
   250  		{1, opcode.Minus, float64(1), 0},
   251  		{1, opcode.Minus, mysql.NewDecimalFromInt(1, 0), 0},
   252  		{uint64(1), opcode.Minus, 1, 0},
   253  		{uint64(1), opcode.Minus, uint64(1), 0},
   254  		{mysql.NewDecimalFromInt(1, 0), opcode.Minus, 1, 0},
   255  		{"1", opcode.Minus, []byte("1"), 0},
   256  
   257  		// mul
   258  		{1, opcode.Mul, 1, 1},
   259  		{1, opcode.Mul, uint64(1), 1},
   260  		{1, opcode.Mul, float64(1), 1},
   261  		{1, opcode.Mul, mysql.NewDecimalFromInt(1, 0), 1},
   262  		{uint64(1), opcode.Mul, 1, 1},
   263  		{uint64(1), opcode.Mul, uint64(1), 1},
   264  		{mysql.Time{}, opcode.Mul, 0, 0},
   265  		{mysql.ZeroDuration, opcode.Mul, 0, 0},
   266  		{mysql.Time{Time: time.Now(), Fsp: 0, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0},
   267  		{mysql.Time{Time: time.Now(), Fsp: 6, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0},
   268  		{mysql.Duration{Duration: 100000000, Fsp: 6}, opcode.Mul, 0, 0},
   269  
   270  		// div
   271  		{1, opcode.Div, float64(1), 1},
   272  		{1, opcode.Div, float64(0), nil},
   273  		{1, opcode.Div, 2, 0.5},
   274  		{1, opcode.Div, 0, nil},
   275  
   276  		// int div
   277  		{1, opcode.IntDiv, 2, 0},
   278  		{1, opcode.IntDiv, uint64(2), 0},
   279  		{1, opcode.IntDiv, 0, nil},
   280  		{1, opcode.IntDiv, uint64(0), nil},
   281  		{uint64(1), opcode.IntDiv, 2, 0},
   282  		{uint64(1), opcode.IntDiv, uint64(2), 0},
   283  		{uint64(1), opcode.IntDiv, 0, nil},
   284  		{uint64(1), opcode.IntDiv, uint64(0), nil},
   285  		{1.0, opcode.IntDiv, 2.0, 0},
   286  		{1.0, opcode.IntDiv, 0, nil},
   287  
   288  		// mod
   289  		{10, opcode.Mod, 2, 0},
   290  		{10, opcode.Mod, uint64(2), 0},
   291  		{10, opcode.Mod, 0, nil},
   292  		{10, opcode.Mod, uint64(0), nil},
   293  		{-10, opcode.Mod, uint64(2), 0},
   294  		{uint64(10), opcode.Mod, 2, 0},
   295  		{uint64(10), opcode.Mod, uint64(2), 0},
   296  		{uint64(10), opcode.Mod, 0, nil},
   297  		{uint64(10), opcode.Mod, uint64(0), nil},
   298  		{uint64(10), opcode.Mod, -2, 0},
   299  		{float64(10), opcode.Mod, 2, 0},
   300  		{float64(10), opcode.Mod, 0, nil},
   301  		{mysql.NewDecimalFromInt(10, 0), opcode.Mod, 2, 0},
   302  		{mysql.NewDecimalFromInt(10, 0), opcode.Mod, 0, nil},
   303  	}
   304  
   305  	for _, t := range tbl {
   306  		expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)}
   307  		v, err := Eval(ctx, expr)
   308  		c.Assert(err, IsNil)
   309  		switch v.Kind() {
   310  		case types.KindNull:
   311  			c.Assert(t.ret, IsNil)
   312  		default:
   313  			// we use float64 as the result type check for all.
   314  			f, err := v.ToFloat64()
   315  			c.Assert(err, IsNil)
   316  
   317  			r, err := types.ToFloat64(t.ret)
   318  			c.Assert(err, IsNil)
   319  			c.Assert(r, Equals, f)
   320  		}
   321  	}
   322  }
   323  
   324  func (s *testEvaluatorSuite) TestCaseWhen(c *C) {
   325  	defer testleak.AfterTest(c)()
   326  	cases := []testCase{
   327  		{
   328  			exprStr:   "case 1 when 1 then 'str1' when 2 then 'str2' end",
   329  			resultStr: "str1",
   330  		},
   331  		{
   332  			exprStr:   "case 2 when 1 then 'str1' when 2 then 'str2' end",
   333  			resultStr: "str2",
   334  		},
   335  		{
   336  			exprStr:   "case 3 when 1 then 'str1' when 2 then 'str2' end",
   337  			resultStr: "<nil>",
   338  		},
   339  		{
   340  			exprStr:   "case 4 when 1 then 'str1' when 2 then 'str2' else 'str3' end",
   341  			resultStr: "str3",
   342  		},
   343  	}
   344  	s.runTests(c, cases)
   345  
   346  	// When expression value changed, result set back to null.
   347  	valExpr := ast.NewValueExpr(1)
   348  	whenClause := &ast.WhenClause{Expr: ast.NewValueExpr(1), Result: ast.NewValueExpr(1)}
   349  	caseExpr := &ast.CaseExpr{
   350  		Value:       valExpr,
   351  		WhenClauses: []*ast.WhenClause{whenClause},
   352  	}
   353  	ctx := mock.NewContext()
   354  	v, err := Eval(ctx, caseExpr)
   355  	c.Assert(err, IsNil)
   356  	c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(1)))
   357  	valExpr.SetValue(4)
   358  	ast.ResetEvaluatedFlag(caseExpr)
   359  	v, err = Eval(ctx, caseExpr)
   360  	c.Assert(err, IsNil)
   361  	c.Assert(v.Kind(), Equals, types.KindNull)
   362  }
   363  
   364  func (s *testEvaluatorSuite) TestCall(c *C) {
   365  	defer testleak.AfterTest(c)()
   366  	ctx := mock.NewContext()
   367  
   368  	// Test case for correct number of arguments
   369  	expr := &ast.FuncCallExpr{
   370  		FnName: model.NewCIStr("date"),
   371  		Args:   []ast.ExprNode{ast.NewValueExpr("2015-12-21 11:11:11")},
   372  	}
   373  	v, err := Eval(ctx, expr)
   374  	c.Assert(err, IsNil)
   375  	c.Assert(v.Kind(), Equals, types.KindMysqlTime)
   376  	c.Assert(v.GetMysqlTime().String(), Equals, "2015-12-21")
   377  
   378  	// Test case for unlimited upper bound
   379  	expr = &ast.FuncCallExpr{
   380  		FnName: model.NewCIStr("concat"),
   381  		Args: []ast.ExprNode{ast.NewValueExpr("Ti"),
   382  			ast.NewValueExpr("D"), ast.NewValueExpr("B")},
   383  	}
   384  	v, err = Eval(ctx, expr)
   385  	c.Assert(err, IsNil)
   386  	c.Assert(v.Kind(), Equals, types.KindString)
   387  	c.Assert(v.GetString(), Equals, "TiDB")
   388  
   389  	// Test case for unknown function
   390  	expr = &ast.FuncCallExpr{
   391  		FnName: model.NewCIStr("unknown"),
   392  		Args:   []ast.ExprNode{},
   393  	}
   394  	_, err = Eval(ctx, expr)
   395  	c.Assert(err, NotNil)
   396  
   397  	// Test case for invalid number of arguments, violating the lower bound
   398  	expr = &ast.FuncCallExpr{
   399  		FnName: model.NewCIStr("date"),
   400  		Args:   []ast.ExprNode{},
   401  	}
   402  	_, err = Eval(ctx, expr)
   403  	c.Assert(err, NotNil)
   404  
   405  	// Test case for invalid number of arguments, violating the upper bound
   406  	expr = &ast.FuncCallExpr{
   407  		FnName: model.NewCIStr("date"),
   408  		Args: []ast.ExprNode{ast.NewValueExpr("2015-12-21"),
   409  			ast.NewValueExpr("2015-12-22")},
   410  	}
   411  	_, err = Eval(ctx, expr)
   412  	c.Assert(err, NotNil)
   413  }
   414  
   415  func (s *testEvaluatorSuite) TestCast(c *C) {
   416  	defer testleak.AfterTest(c)()
   417  	f := types.NewFieldType(mysql.TypeLonglong)
   418  
   419  	expr := &ast.FuncCastExpr{
   420  		Expr: ast.NewValueExpr(1),
   421  		Tp:   f,
   422  	}
   423  	ast.SetFlag(expr)
   424  	ctx := mock.NewContext()
   425  	v, err := Eval(ctx, expr)
   426  	c.Assert(err, IsNil)
   427  	c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(1)))
   428  
   429  	f.Flag |= mysql.UnsignedFlag
   430  	v, err = Eval(ctx, expr)
   431  	c.Assert(err, IsNil)
   432  	c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(1)))
   433  
   434  	f.Tp = mysql.TypeString
   435  	f.Charset = charset.CharsetBin
   436  	v, err = Eval(ctx, expr)
   437  	c.Assert(err, IsNil)
   438  	c.Assert(v, testutil.DatumEquals, types.NewDatum([]byte("1")))
   439  
   440  	f.Tp = mysql.TypeString
   441  	f.Charset = "utf8"
   442  	v, err = Eval(ctx, expr)
   443  	c.Assert(err, IsNil)
   444  	c.Assert(v, testutil.DatumEquals, types.NewDatum("1"))
   445  
   446  	expr.Expr = ast.NewValueExpr(nil)
   447  	v, err = Eval(ctx, expr)
   448  	c.Assert(err, IsNil)
   449  	c.Assert(v.Kind(), Equals, types.KindNull)
   450  }
   451  
   452  func (s *testEvaluatorSuite) TestExtract(c *C) {
   453  	defer testleak.AfterTest(c)()
   454  	str := "2011-11-11 10:10:10.123456"
   455  	tbl := []struct {
   456  		Unit   string
   457  		Expect int64
   458  	}{
   459  		{"MICROSECOND", 123456},
   460  		{"SECOND", 10},
   461  		{"MINUTE", 10},
   462  		{"HOUR", 10},
   463  		{"DAY", 11},
   464  		{"WEEK", 45},
   465  		{"MONTH", 11},
   466  		{"QUARTER", 4},
   467  		{"YEAR", 2011},
   468  		{"SECOND_MICROSECOND", 10123456},
   469  		{"MINUTE_MICROSECOND", 1010123456},
   470  		{"MINUTE_SECOND", 1010},
   471  		{"HOUR_MICROSECOND", 101010123456},
   472  		{"HOUR_SECOND", 101010},
   473  		{"HOUR_MINUTE", 1010},
   474  		{"DAY_MICROSECOND", 11101010123456},
   475  		{"DAY_SECOND", 11101010},
   476  		{"DAY_MINUTE", 111010},
   477  		{"DAY_HOUR", 1110},
   478  		{"YEAR_MONTH", 201111},
   479  	}
   480  	ctx := mock.NewContext()
   481  	for _, t := range tbl {
   482  		e := &ast.FuncCallExpr{
   483  			FnName: model.NewCIStr("EXTRACT"),
   484  			Args:   []ast.ExprNode{ast.NewValueExpr(t.Unit), ast.NewValueExpr(str)},
   485  		}
   486  		v, err := Eval(ctx, e)
   487  		c.Assert(err, IsNil)
   488  		c.Assert(v, testutil.DatumEquals, types.NewDatum(t.Expect))
   489  	}
   490  
   491  	// Test nil
   492  	e := &ast.FuncCallExpr{
   493  		FnName: model.NewCIStr("EXTRACT"),
   494  		Args:   []ast.ExprNode{ast.NewValueExpr("SECOND"), ast.NewValueExpr(nil)},
   495  	}
   496  
   497  	v, err := Eval(ctx, e)
   498  	c.Assert(err, IsNil)
   499  	c.Assert(v.Kind(), Equals, types.KindNull)
   500  }
   501  
   502  func (s *testEvaluatorSuite) TestPatternIn(c *C) {
   503  	defer testleak.AfterTest(c)()
   504  	cases := []testCase{
   505  		{
   506  			exprStr:   "1 not in (1, 2, 3)",
   507  			resultStr: "0",
   508  		},
   509  		{
   510  			exprStr:   "1 in (1, 2, 3)",
   511  			resultStr: "1",
   512  		},
   513  		{
   514  			exprStr:   "1 in (2, 3)",
   515  			resultStr: "0",
   516  		},
   517  		{
   518  			exprStr:   "NULL in (2, 3)",
   519  			resultStr: "<nil>",
   520  		},
   521  		{
   522  			exprStr:   "NULL not in (2, 3)",
   523  			resultStr: "<nil>",
   524  		},
   525  		{
   526  			exprStr:   "NULL in (NULL, 3)",
   527  			resultStr: "<nil>",
   528  		},
   529  		{
   530  			exprStr:   "1 in (1, NULL)",
   531  			resultStr: "1",
   532  		},
   533  		{
   534  			exprStr:   "1 in (NULL, 1)",
   535  			resultStr: "1",
   536  		},
   537  		{
   538  			exprStr:   "2 in (1, NULL)",
   539  			resultStr: "<nil>",
   540  		},
   541  		{
   542  			exprStr:   "(-(23)++46/51*+51) in (+23)",
   543  			resultStr: "0",
   544  		},
   545  	}
   546  	s.runTests(c, cases)
   547  }
   548  
   549  func (s *testEvaluatorSuite) TestIsNull(c *C) {
   550  	defer testleak.AfterTest(c)()
   551  	cases := []testCase{
   552  		{
   553  			exprStr:   "1 IS NULL",
   554  			resultStr: "0",
   555  		},
   556  		{
   557  			exprStr:   "1 IS NOT NULL",
   558  			resultStr: "1",
   559  		},
   560  		{
   561  			exprStr:   "NULL IS NULL",
   562  			resultStr: "1",
   563  		},
   564  		{
   565  			exprStr:   "NULL IS NOT NULL",
   566  			resultStr: "0",
   567  		},
   568  	}
   569  	s.runTests(c, cases)
   570  }
   571  
   572  func (s *testEvaluatorSuite) TestIsTruth(c *C) {
   573  	defer testleak.AfterTest(c)()
   574  	cases := []testCase{
   575  		{
   576  			exprStr:   "1 IS TRUE",
   577  			resultStr: "1",
   578  		},
   579  		{
   580  			exprStr:   "2 IS TRUE",
   581  			resultStr: "1",
   582  		},
   583  		{
   584  			exprStr:   "0 IS TRUE",
   585  			resultStr: "0",
   586  		},
   587  		{
   588  			exprStr:   "NULL IS TRUE",
   589  			resultStr: "0",
   590  		},
   591  		{
   592  			exprStr:   "1 IS FALSE",
   593  			resultStr: "0",
   594  		},
   595  		{
   596  			exprStr:   "2 IS FALSE",
   597  			resultStr: "0",
   598  		},
   599  		{
   600  			exprStr:   "0 IS FALSE",
   601  			resultStr: "1",
   602  		},
   603  		{
   604  			exprStr:   "NULL IS NOT FALSE",
   605  			resultStr: "1",
   606  		},
   607  		{
   608  			exprStr:   "1 IS NOT TRUE",
   609  			resultStr: "0",
   610  		},
   611  		{
   612  			exprStr:   "2 IS NOT TRUE",
   613  			resultStr: "0",
   614  		},
   615  		{
   616  			exprStr:   "0 IS NOT TRUE",
   617  			resultStr: "1",
   618  		},
   619  		{
   620  			exprStr:   "NULL IS NOT TRUE",
   621  			resultStr: "1",
   622  		},
   623  		{
   624  			exprStr:   "1 IS NOT FALSE",
   625  			resultStr: "1",
   626  		},
   627  		{
   628  			exprStr:   "2 IS NOT FALSE",
   629  			resultStr: "1",
   630  		},
   631  		{
   632  			exprStr:   "0 IS NOT FALSE",
   633  			resultStr: "0",
   634  		},
   635  		{
   636  			exprStr:   "NULL IS NOT FALSE",
   637  			resultStr: "1",
   638  		},
   639  	}
   640  	s.runTests(c, cases)
   641  }
   642  
   643  func (s *testEvaluatorSuite) TestLike(c *C) {
   644  	defer testleak.AfterTest(c)()
   645  	tbl := []struct {
   646  		pattern string
   647  		input   string
   648  		escape  byte
   649  		match   bool
   650  	}{
   651  		{"", "a", '\\', false},
   652  		{"a", "a", '\\', true},
   653  		{"a", "b", '\\', false},
   654  		{"aA", "aA", '\\', true},
   655  		{"_", "a", '\\', true},
   656  		{"_", "ab", '\\', false},
   657  		{"__", "b", '\\', false},
   658  		{"_ab", "AAB", '\\', true},
   659  		{"%", "abcd", '\\', true},
   660  		{"%", "", '\\', true},
   661  		{"%a", "AAA", '\\', true},
   662  		{"%b", "AAA", '\\', false},
   663  		{"b%", "BBB", '\\', true},
   664  		{"%a%", "BBB", '\\', false},
   665  		{"%a%", "BAB", '\\', true},
   666  		{"a%", "BBB", '\\', false},
   667  		{`\%a`, `%a`, '\\', true},
   668  		{`\%a`, `aa`, '\\', false},
   669  		{`\_a`, `_a`, '\\', true},
   670  		{`\_a`, `aa`, '\\', false},
   671  		{`\\_a`, `\xa`, '\\', true},
   672  		{`\a\b`, `\a\b`, '\\', true},
   673  		{"%%_", `abc`, '\\', true},
   674  		{`+_a`, `_a`, '+', true},
   675  		{`+%a`, `%a`, '+', true},
   676  		{`\%a`, `%a`, '+', false},
   677  		{`++a`, `+a`, '+', true},
   678  		{`++_a`, `+xa`, '+', true},
   679  	}
   680  	for _, v := range tbl {
   681  		patChars, patTypes := compilePattern(v.pattern, v.escape)
   682  		match := doMatch(v.input, patChars, patTypes)
   683  		c.Assert(match, Equals, v.match, Commentf("%v", v))
   684  	}
   685  	cases := []testCase{
   686  		{
   687  			exprStr:   "'a' LIKE ''",
   688  			resultStr: "0",
   689  		},
   690  		{
   691  			exprStr:   "'a' LIKE 'a'",
   692  			resultStr: "1",
   693  		},
   694  		{
   695  			exprStr:   "'a' LIKE 'b'",
   696  			resultStr: "0",
   697  		},
   698  		{
   699  			exprStr:   "'aA' LIKE 'Aa'",
   700  			resultStr: "1",
   701  		},
   702  		{
   703  			exprStr:   "'aAb' LIKE 'Aa%'",
   704  			resultStr: "1",
   705  		},
   706  		{
   707  			exprStr:   "'aAb' LIKE 'Aa_'",
   708  			resultStr: "1",
   709  		},
   710  	}
   711  	s.runTests(c, cases)
   712  }
   713  
   714  func (s *testEvaluatorSuite) TestRegexp(c *C) {
   715  	defer testleak.AfterTest(c)()
   716  	tbl := []struct {
   717  		pattern string
   718  		input   string
   719  		match   int64
   720  	}{
   721  		{"^$", "a", 0},
   722  		{"a", "a", 1},
   723  		{"a", "b", 0},
   724  		{"aA", "aA", 1},
   725  		{".", "a", 1},
   726  		{"^.$", "ab", 0},
   727  		{"..", "b", 0},
   728  		{".ab", "aab", 1},
   729  		{".*", "abcd", 1},
   730  	}
   731  	ctx := mock.NewContext()
   732  	for _, v := range tbl {
   733  		pattern := &ast.PatternRegexpExpr{
   734  			Pattern: ast.NewValueExpr(v.pattern),
   735  			Expr:    ast.NewValueExpr(v.input),
   736  		}
   737  		match, err := Eval(ctx, pattern)
   738  		c.Assert(err, IsNil)
   739  		c.Assert(match, testutil.DatumEquals, types.NewDatum(v.match), Commentf("%v", v))
   740  	}
   741  }
   742  
   743  func (s *testEvaluatorSuite) TestUnaryOp(c *C) {
   744  	defer testleak.AfterTest(c)()
   745  	tbl := []struct {
   746  		arg    interface{}
   747  		op     opcode.Op
   748  		result interface{}
   749  	}{
   750  		// test NOT.
   751  		{1, opcode.Not, int64(0)},
   752  		{0, opcode.Not, int64(1)},
   753  		{nil, opcode.Not, nil},
   754  		{mysql.Hex{Value: 0}, opcode.Not, int64(1)},
   755  		{mysql.Bit{Value: 0, Width: 1}, opcode.Not, int64(1)},
   756  		{mysql.Enum{Name: "a", Value: 1}, opcode.Not, int64(0)},
   757  		{mysql.Set{Name: "a", Value: 1}, opcode.Not, int64(0)},
   758  
   759  		// test BitNeg.
   760  		{nil, opcode.BitNeg, nil},
   761  		{-1, opcode.BitNeg, uint64(0)},
   762  
   763  		// test Plus.
   764  		{nil, opcode.Plus, nil},
   765  		{float64(1.0), opcode.Plus, float64(1.0)},
   766  		{int64(1), opcode.Plus, int64(1)},
   767  		{int64(1), opcode.Plus, int64(1)},
   768  		{uint64(1), opcode.Plus, uint64(1)},
   769  		{"1.0", opcode.Plus, "1.0"},
   770  		{[]byte("1.0"), opcode.Plus, []byte("1.0")},
   771  		{mysql.Hex{Value: 1}, opcode.Plus, mysql.Hex{Value: 1}},
   772  		{mysql.Bit{Value: 1, Width: 1}, opcode.Plus, mysql.Bit{Value: 1, Width: 1}},
   773  		{true, opcode.Plus, int64(1)},
   774  		{false, opcode.Plus, int64(0)},
   775  		{mysql.Enum{Name: "a", Value: 1}, opcode.Plus, mysql.Enum{Name: "a", Value: 1}},
   776  		{mysql.Set{Name: "a", Value: 1}, opcode.Plus, mysql.Set{Name: "a", Value: 1}},
   777  
   778  		// test Minus.
   779  		{nil, opcode.Minus, nil},
   780  		{float64(1.0), opcode.Minus, float64(-1.0)},
   781  		{int64(1), opcode.Minus, int64(-1)},
   782  		{int64(1), opcode.Minus, int64(-1)},
   783  		{uint64(1), opcode.Minus, -int64(1)},
   784  		{"1.0", opcode.Minus, -1.0},
   785  		{[]byte("1.0"), opcode.Minus, -1.0},
   786  		{mysql.Hex{Value: 1}, opcode.Minus, -1.0},
   787  		{mysql.Bit{Value: 1, Width: 1}, opcode.Minus, -1.0},
   788  		{true, opcode.Minus, int64(-1)},
   789  		{false, opcode.Minus, int64(0)},
   790  		{mysql.Enum{Name: "a", Value: 1}, opcode.Minus, -1.0},
   791  		{mysql.Set{Name: "a", Value: 1}, opcode.Minus, -1.0},
   792  	}
   793  	ctx := mock.NewContext()
   794  	for i, t := range tbl {
   795  		expr := &ast.UnaryOperationExpr{}
   796  		expr.Op = t.op
   797  		expr.V = ast.NewValueExpr(t.arg)
   798  		result, err := Eval(ctx, expr)
   799  		c.Assert(err, IsNil)
   800  		c.Assert(result, testutil.DatumEquals, types.NewDatum(t.result), Commentf("%d", i))
   801  	}
   802  
   803  	tbl = []struct {
   804  		arg    interface{}
   805  		op     opcode.Op
   806  		result interface{}
   807  	}{
   808  		{mysql.NewDecimalFromInt(1, 0), opcode.Plus, mysql.NewDecimalFromInt(1, 0)},
   809  		{mysql.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: mysql.DefaultFsp}, opcode.Plus,
   810  			mysql.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: mysql.DefaultFsp}},
   811  		{mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Plus, mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}},
   812  
   813  		{mysql.NewDecimalFromInt(1, 0), opcode.Minus, mysql.NewDecimalFromInt(-1, 0)},
   814  		{mysql.ZeroDuration, opcode.Minus, mysql.NewDecimalFromInt(0, 0)},
   815  		{mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Minus, mysql.NewDecimalFromInt(-20091110230000, 0)},
   816  	}
   817  
   818  	for _, t := range tbl {
   819  		expr := &ast.UnaryOperationExpr{Op: t.op, V: ast.NewValueExpr(t.arg)}
   820  
   821  		result, err := Eval(ctx, expr)
   822  		c.Assert(err, IsNil)
   823  
   824  		ret, err := result.CompareDatum(types.NewDatum(t.result))
   825  		c.Assert(err, IsNil)
   826  		c.Assert(ret, Equals, 0)
   827  	}
   828  }
   829  
   830  func (s *testEvaluatorSuite) TestColumnNameExpr(c *C) {
   831  	defer testleak.AfterTest(c)()
   832  	ctx := mock.NewContext()
   833  	value1 := ast.NewValueExpr(1)
   834  	rf := &ast.ResultField{Expr: value1}
   835  	expr := &ast.ColumnNameExpr{Refer: rf}
   836  
   837  	ast.SetFlag(expr)
   838  	result, err := Eval(ctx, expr)
   839  	c.Assert(err, IsNil)
   840  	c.Assert(result, testutil.DatumEquals, types.NewDatum(int64(1)))
   841  
   842  	value2 := ast.NewValueExpr(2)
   843  	rf.Expr = value2
   844  	result, err = Eval(ctx, expr)
   845  	c.Assert(err, IsNil)
   846  	c.Assert(result, testutil.DatumEquals, types.NewDatum(int64(2)))
   847  }
   848  
   849  func (s *testEvaluatorSuite) TestAggFuncAvg(c *C) {
   850  	defer testleak.AfterTest(c)()
   851  	ctx := mock.NewContext()
   852  	avg := &ast.AggregateFuncExpr{
   853  		F: ast.AggFuncAvg,
   854  	}
   855  	avg.CurrentGroup = "emptyGroup"
   856  	ast.SetFlag(avg)
   857  	result, err := Eval(ctx, avg)
   858  	c.Assert(err, IsNil)
   859  	// Empty group should return nil.
   860  	c.Assert(result.Kind(), Equals, types.KindNull)
   861  
   862  	avg.Args = []ast.ExprNode{ast.NewValueExpr(2)}
   863  	avg.Update()
   864  	avg.Args = []ast.ExprNode{ast.NewValueExpr(4)}
   865  	avg.Update()
   866  
   867  	result, err = Eval(ctx, avg)
   868  	c.Assert(err, IsNil)
   869  	expect, _ := mysql.ConvertToDecimal(3)
   870  	c.Assert(result.Kind(), Equals, types.KindMysqlDecimal)
   871  	c.Assert(result.GetMysqlDecimal().Equals(expect), IsTrue)
   872  }
   873  
   874  func (s *testEvaluatorSuite) TestGetTimeValue(c *C) {
   875  	defer testleak.AfterTest(c)()
   876  	v, err := GetTimeValue(nil, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
   877  	c.Assert(err, IsNil)
   878  
   879  	c.Assert(v.Kind(), Equals, types.KindMysqlTime)
   880  	timeValue := v.GetMysqlTime()
   881  	c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
   882  
   883  	ctx := mock.NewContext()
   884  	variable.BindSessionVars(ctx)
   885  	sessionVars := variable.GetSessionVars(ctx)
   886  
   887  	sessionVars.Systems["timestamp"] = ""
   888  	v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
   889  	c.Assert(err, IsNil)
   890  
   891  	c.Assert(v.Kind(), Equals, types.KindMysqlTime)
   892  	timeValue = v.GetMysqlTime()
   893  	c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
   894  
   895  	sessionVars.Systems["timestamp"] = "0"
   896  	v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
   897  	c.Assert(err, IsNil)
   898  
   899  	c.Assert(v.Kind(), Equals, types.KindMysqlTime)
   900  	timeValue = v.GetMysqlTime()
   901  	c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
   902  
   903  	delete(sessionVars.Systems, "timestamp")
   904  	v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, mysql.MinFsp)
   905  	c.Assert(err, IsNil)
   906  
   907  	c.Assert(v.Kind(), Equals, types.KindMysqlTime)
   908  	timeValue = v.GetMysqlTime()
   909  	c.Assert(timeValue.String(), Equals, "2012-12-12 00:00:00")
   910  
   911  	sessionVars.Systems["timestamp"] = "1234"
   912  
   913  	tbl := []struct {
   914  		Expr interface{}
   915  		Ret  interface{}
   916  	}{
   917  		{"2012-12-12 00:00:00", "2012-12-12 00:00:00"},
   918  		{CurrentTimestamp, time.Unix(1234, 0).Format(mysql.TimeFormat)},
   919  		{ZeroTimestamp, "0000-00-00 00:00:00"},
   920  		{ast.NewValueExpr("2012-12-12 00:00:00"), "2012-12-12 00:00:00"},
   921  		{ast.NewValueExpr(int64(0)), "0000-00-00 00:00:00"},
   922  		{ast.NewValueExpr(nil), nil},
   923  		{&ast.FuncCallExpr{FnName: model.NewCIStr(CurrentTimestamp)}, CurrentTimestamp},
   924  		{&ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(int64(0))}, "0000-00-00 00:00:00"},
   925  	}
   926  
   927  	for i, t := range tbl {
   928  		comment := Commentf("expr: %d", i)
   929  		v, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, mysql.MinFsp)
   930  		c.Assert(err, IsNil)
   931  
   932  		switch v.Kind() {
   933  		case types.KindMysqlTime:
   934  			c.Assert(v.GetMysqlTime().String(), DeepEquals, t.Ret, comment)
   935  		default:
   936  			c.Assert(v.GetValue(), DeepEquals, t.Ret, comment)
   937  		}
   938  	}
   939  
   940  	errTbl := []struct {
   941  		Expr interface{}
   942  	}{
   943  		{"2012-13-12 00:00:00"},
   944  		{ast.NewValueExpr("2012-13-12 00:00:00")},
   945  		{ast.NewValueExpr(int64(1))},
   946  		{&ast.FuncCallExpr{FnName: model.NewCIStr("xxx")}},
   947  		{&ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(int64(1))}},
   948  	}
   949  
   950  	for _, t := range errTbl {
   951  		_, err := GetTimeValue(ctx, t.Expr, mysql.TypeTimestamp, mysql.MinFsp)
   952  		c.Assert(err, NotNil)
   953  	}
   954  }
   955  
   956  func (s *testEvaluatorSuite) TestIsCurrentTimeExpr(c *C) {
   957  	defer testleak.AfterTest(c)()
   958  	v := IsCurrentTimeExpr(ast.NewValueExpr("abc"))
   959  	c.Assert(v, IsFalse)
   960  
   961  	v = IsCurrentTimeExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")})
   962  	c.Assert(v, IsTrue)
   963  }
   964  
   965  func (s *testEvaluatorSuite) TestEvaluatedFlag(c *C) {
   966  	l := ast.NewValueExpr(int64(1))
   967  	r := ast.NewValueExpr(int64(2))
   968  	b := &ast.BinaryOperationExpr{L: l, R: r, Op: opcode.Plus}
   969  	ast.SetFlag(b)
   970  	c.Assert(ast.IsPreEvaluable(b), Equals, true)
   971  	ctx := mock.NewContext()
   972  	d, err := Eval(ctx, b)
   973  	c.Assert(ast.IsEvaluated(b), Equals, true)
   974  	c.Assert(err, IsNil)
   975  	c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3))
   976  
   977  	funcCall := &ast.FuncCallExpr{
   978  		FnName: model.NewCIStr("abs"),
   979  		Args:   []ast.ExprNode{ast.NewValueExpr(int(-1))},
   980  	}
   981  	b = &ast.BinaryOperationExpr{L: funcCall, R: r, Op: opcode.Plus}
   982  	ast.ResetEvaluatedFlag(b)
   983  	ast.SetFlag(b)
   984  	c.Assert(ast.IsPreEvaluable(b), Equals, true)
   985  	d, err = Eval(ctx, b)
   986  	c.Assert(ast.IsEvaluated(b), Equals, false)
   987  	c.Assert(err, IsNil)
   988  	c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3))
   989  
   990  	rf := &ast.ResultField{Expr: ast.NewValueExpr(int64(1))}
   991  	colExpr := &ast.ColumnNameExpr{Refer: rf}
   992  	b = &ast.BinaryOperationExpr{L: colExpr, R: r, Op: opcode.Plus}
   993  	ast.ResetEvaluatedFlag(b)
   994  	ast.SetFlag(b)
   995  	c.Assert(ast.IsPreEvaluable(b), Equals, false)
   996  	d, err = Eval(ctx, b)
   997  	c.Assert(ast.IsEvaluated(b), Equals, false)
   998  	c.Assert(err, IsNil)
   999  	c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3))
  1000  }
  1001  
  1002  func (s *testEvaluatorSuite) TestMod(c *C) {
  1003  	cases := []testCase{
  1004  		{
  1005  			exprStr:   "MOD(234, 10)",
  1006  			resultStr: "4",
  1007  		},
  1008  		{
  1009  			exprStr:   "MOD(29, 9)",
  1010  			resultStr: "2",
  1011  		},
  1012  		{
  1013  			exprStr:   "MOD(34.5, 3)",
  1014  			resultStr: "1.5",
  1015  		},
  1016  	}
  1017  	s.runTests(c, cases)
  1018  }