github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/evaluator_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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 memex
    15  
    16  import (
    17  	"sync/atomic"
    18  	"testing"
    19  	"time"
    20  
    21  	. "github.com/whtcorpsinc/check"
    22  	"github.com/whtcorpsinc/BerolinaSQL"
    23  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    24  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    25  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    26  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    27  	"github.com/whtcorpsinc/milevadb/types"
    28  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    29  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    30  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    31  	"github.com/whtcorpsinc/milevadb/soliton/solitonutil"
    32  )
    33  
    34  var _ = SerialSuites(&testEvaluatorSerialSuites{})
    35  var _ = Suite(&testEvaluatorSuite{})
    36  var _ = Suite(&testVectorizeSuite1{})
    37  var _ = Suite(&testVectorizeSuite2{})
    38  
    39  func TestT(t *testing.T) {
    40  	testleak.BeforeTest()
    41  	defer testleak.AfterTestT(t)()
    42  
    43  	CustomVerboseFlag = true
    44  	*CustomParallelSuiteFlag = true
    45  	TestingT(t)
    46  }
    47  
    48  type testEvaluatorSuiteBase struct {
    49  	*BerolinaSQL.BerolinaSQL
    50  	ctx stochastikctx.Context
    51  }
    52  
    53  type testEvaluatorSuite struct {
    54  	testEvaluatorSuiteBase
    55  }
    56  
    57  type testVectorizeSuite1 struct {
    58  	testEvaluatorSuiteBase
    59  }
    60  
    61  type testVectorizeSuite2 struct {
    62  	testEvaluatorSuiteBase
    63  }
    64  
    65  type testEvaluatorSerialSuites struct {
    66  	testEvaluatorSuiteBase
    67  }
    68  
    69  func (s *testEvaluatorSuiteBase) SetUpSuite(c *C) {
    70  	s.BerolinaSQL = BerolinaSQL.New()
    71  }
    72  
    73  func (s *testEvaluatorSuiteBase) TearDownSuite(c *C) {
    74  }
    75  
    76  func (s *testEvaluatorSuiteBase) SetUpTest(c *C) {
    77  	s.ctx = mock.NewContext()
    78  	s.ctx.GetStochastikVars().StmtCtx.TimeZone = time.Local
    79  	sc := s.ctx.GetStochastikVars().StmtCtx
    80  	sc.TruncateAsWarning = true
    81  	s.ctx.GetStochastikVars().SetSystemVar("max_allowed_packet", "67108864")
    82  	s.ctx.GetStochastikVars().CausetDeferredCausetID = 0
    83  }
    84  
    85  func (s *testEvaluatorSuiteBase) TearDownTest(c *C) {
    86  	s.ctx.GetStochastikVars().StmtCtx.SetWarnings(nil)
    87  }
    88  
    89  func (s *testEvaluatorSuiteBase) HoTTToFieldType(HoTT byte) types.FieldType {
    90  	ft := types.FieldType{}
    91  	switch HoTT {
    92  	case types.HoTTNull:
    93  		ft.Tp = allegrosql.TypeNull
    94  	case types.HoTTInt64:
    95  		ft.Tp = allegrosql.TypeLonglong
    96  	case types.HoTTUint64:
    97  		ft.Tp = allegrosql.TypeLonglong
    98  		ft.Flag |= allegrosql.UnsignedFlag
    99  	case types.HoTTMinNotNull:
   100  		ft.Tp = allegrosql.TypeLonglong
   101  	case types.HoTTMaxValue:
   102  		ft.Tp = allegrosql.TypeLonglong
   103  	case types.HoTTFloat32:
   104  		ft.Tp = allegrosql.TypeDouble
   105  	case types.HoTTFloat64:
   106  		ft.Tp = allegrosql.TypeDouble
   107  	case types.HoTTString:
   108  		ft.Tp = allegrosql.TypeVarString
   109  	case types.HoTTBytes:
   110  		ft.Tp = allegrosql.TypeVarString
   111  	case types.HoTTMysqlEnum:
   112  		ft.Tp = allegrosql.TypeEnum
   113  	case types.HoTTMysqlSet:
   114  		ft.Tp = allegrosql.TypeSet
   115  	case types.HoTTInterface:
   116  		ft.Tp = allegrosql.TypeVarString
   117  	case types.HoTTMysqlDecimal:
   118  		ft.Tp = allegrosql.TypeNewDecimal
   119  	case types.HoTTMysqlDuration:
   120  		ft.Tp = allegrosql.TypeDuration
   121  	case types.HoTTMysqlTime:
   122  		ft.Tp = allegrosql.TypeDatetime
   123  	case types.HoTTBinaryLiteral:
   124  		ft.Tp = allegrosql.TypeVarString
   125  		ft.Charset = charset.CharsetBin
   126  		ft.DefCauslate = charset.DefCauslationBin
   127  	case types.HoTTMysqlBit:
   128  		ft.Tp = allegrosql.TypeBit
   129  	case types.HoTTMysqlJSON:
   130  		ft.Tp = allegrosql.TypeJSON
   131  	}
   132  	return ft
   133  }
   134  
   135  func (s *testEvaluatorSuiteBase) datumsToConstants(datums []types.Causet) []Expression {
   136  	constants := make([]Expression, 0, len(datums))
   137  	for _, d := range datums {
   138  		ft := s.HoTTToFieldType(d.HoTT())
   139  		if types.IsNonBinaryStr(&ft) {
   140  			ft.DefCauslate = d.DefCauslation()
   141  		}
   142  		ft.Flen, ft.Decimal = types.UnspecifiedLength, types.UnspecifiedLength
   143  		constants = append(constants, &Constant{Value: d, RetType: &ft})
   144  	}
   145  	return constants
   146  }
   147  
   148  func (s *testEvaluatorSuiteBase) primitiveValsToConstants(args []interface{}) []Expression {
   149  	cons := s.datumsToConstants(types.MakeCausets(args...))
   150  	char, defCaus := s.ctx.GetStochastikVars().GetCharsetInfo()
   151  	for i, arg := range args {
   152  		types.DefaultTypeForValue(arg, cons[i].GetType(), char, defCaus)
   153  	}
   154  	return cons
   155  }
   156  
   157  func (s *testEvaluatorSuite) TestSleep(c *C) {
   158  	ctx := mock.NewContext()
   159  	sessVars := ctx.GetStochastikVars()
   160  
   161  	fc := funcs[ast.Sleep]
   162  	// non-strict perceptron
   163  	sessVars.StrictALLEGROSQLMode = false
   164  	d := make([]types.Causet, 1)
   165  	f, err := fc.getFunction(ctx, s.datumsToConstants(d))
   166  	c.Assert(err, IsNil)
   167  	ret, isNull, err := f.evalInt(chunk.Row{})
   168  	c.Assert(err, IsNil)
   169  	c.Assert(isNull, IsFalse)
   170  	c.Assert(ret, Equals, int64(0))
   171  	d[0].SetInt64(-1)
   172  	f, err = fc.getFunction(ctx, s.datumsToConstants(d))
   173  	c.Assert(err, IsNil)
   174  	ret, isNull, err = f.evalInt(chunk.Row{})
   175  	c.Assert(err, IsNil)
   176  	c.Assert(isNull, IsFalse)
   177  	c.Assert(ret, Equals, int64(0))
   178  
   179  	// for error case under the strict perceptron
   180  	sessVars.StrictALLEGROSQLMode = true
   181  	d[0].SetNull()
   182  	_, err = fc.getFunction(ctx, s.datumsToConstants(d))
   183  	c.Assert(err, IsNil)
   184  	_, isNull, err = f.evalInt(chunk.Row{})
   185  	c.Assert(err, NotNil)
   186  	c.Assert(isNull, IsFalse)
   187  	d[0].SetFloat64(-2.5)
   188  	_, err = fc.getFunction(ctx, s.datumsToConstants(d))
   189  	c.Assert(err, IsNil)
   190  	_, isNull, err = f.evalInt(chunk.Row{})
   191  	c.Assert(err, NotNil)
   192  	c.Assert(isNull, IsFalse)
   193  
   194  	// strict perceptron
   195  	d[0].SetFloat64(0.5)
   196  	start := time.Now()
   197  	f, err = fc.getFunction(ctx, s.datumsToConstants(d))
   198  	c.Assert(err, IsNil)
   199  	ret, isNull, err = f.evalInt(chunk.Row{})
   200  	c.Assert(err, IsNil)
   201  	c.Assert(isNull, IsFalse)
   202  	c.Assert(ret, Equals, int64(0))
   203  	sub := time.Since(start)
   204  	c.Assert(sub.Nanoseconds(), GreaterEqual, int64(0.5*1e9))
   205  
   206  	d[0].SetFloat64(3)
   207  	f, err = fc.getFunction(ctx, s.datumsToConstants(d))
   208  	c.Assert(err, IsNil)
   209  	start = time.Now()
   210  	go func() {
   211  		time.Sleep(1 * time.Second)
   212  		atomic.CompareAndSwapUint32(&ctx.GetStochastikVars().Killed, 0, 1)
   213  	}()
   214  	ret, isNull, err = f.evalInt(chunk.Row{})
   215  	sub = time.Since(start)
   216  	c.Assert(err, IsNil)
   217  	c.Assert(isNull, IsFalse)
   218  	c.Assert(ret, Equals, int64(1))
   219  	c.Assert(sub.Nanoseconds(), LessEqual, int64(2*1e9))
   220  	c.Assert(sub.Nanoseconds(), GreaterEqual, int64(1*1e9))
   221  }
   222  
   223  func (s *testEvaluatorSuite) TestBinopComparison(c *C) {
   224  	tbl := []struct {
   225  		lhs    interface{}
   226  		op     string
   227  		rhs    interface{}
   228  		result int64 // 0 for false, 1 for true
   229  	}{
   230  		// test EQ
   231  		{1, ast.EQ, 2, 0},
   232  		{false, ast.EQ, false, 1},
   233  		{false, ast.EQ, true, 0},
   234  		{true, ast.EQ, true, 1},
   235  		{true, ast.EQ, false, 0},
   236  		{"1", ast.EQ, true, 1},
   237  		{"1", ast.EQ, false, 0},
   238  
   239  		// test NEQ
   240  		{1, ast.NE, 2, 1},
   241  		{false, ast.NE, false, 0},
   242  		{false, ast.NE, true, 1},
   243  		{true, ast.NE, true, 0},
   244  		{"1", ast.NE, true, 0},
   245  		{"1", ast.NE, false, 1},
   246  
   247  		// test GT, GE
   248  		{1, ast.GT, 0, 1},
   249  		{1, ast.GT, 1, 0},
   250  		{1, ast.GE, 1, 1},
   251  		{3.14, ast.GT, 3, 1},
   252  		{3.14, ast.GE, 3.14, 1},
   253  
   254  		// test LT, LE
   255  		{1, ast.LT, 2, 1},
   256  		{1, ast.LT, 1, 0},
   257  		{1, ast.LE, 1, 1},
   258  	}
   259  	for _, t := range tbl {
   260  		fc := funcs[t.op]
   261  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   262  		c.Assert(err, IsNil)
   263  		v, err := evalBuiltinFunc(f, chunk.Row{})
   264  		c.Assert(err, IsNil)
   265  		val, err := v.ToBool(s.ctx.GetStochastikVars().StmtCtx)
   266  		c.Assert(err, IsNil)
   267  		c.Assert(val, Equals, t.result)
   268  	}
   269  
   270  	// test nil
   271  	nilTbl := []struct {
   272  		lhs interface{}
   273  		op  string
   274  		rhs interface{}
   275  	}{
   276  		{nil, ast.EQ, nil},
   277  		{nil, ast.EQ, 1},
   278  		{nil, ast.NE, nil},
   279  		{nil, ast.NE, 1},
   280  		{nil, ast.LT, nil},
   281  		{nil, ast.LT, 1},
   282  		{nil, ast.LE, nil},
   283  		{nil, ast.LE, 1},
   284  		{nil, ast.GT, nil},
   285  		{nil, ast.GT, 1},
   286  		{nil, ast.GE, nil},
   287  		{nil, ast.GE, 1},
   288  	}
   289  
   290  	for _, t := range nilTbl {
   291  		fc := funcs[t.op]
   292  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   293  		c.Assert(err, IsNil)
   294  		v, err := evalBuiltinFunc(f, chunk.Row{})
   295  		c.Assert(err, IsNil)
   296  		c.Assert(v.HoTT(), Equals, types.HoTTNull)
   297  	}
   298  }
   299  
   300  func (s *testEvaluatorSuite) TestBinopLogic(c *C) {
   301  	tbl := []struct {
   302  		lhs interface{}
   303  		op  string
   304  		rhs interface{}
   305  		ret interface{}
   306  	}{
   307  		{nil, ast.LogicAnd, 1, nil},
   308  		{nil, ast.LogicAnd, 0, 0},
   309  		{nil, ast.LogicOr, 1, 1},
   310  		{nil, ast.LogicOr, 0, nil},
   311  		{nil, ast.LogicXor, 1, nil},
   312  		{nil, ast.LogicXor, 0, nil},
   313  		{1, ast.LogicAnd, 0, 0},
   314  		{1, ast.LogicAnd, 1, 1},
   315  		{1, ast.LogicOr, 0, 1},
   316  		{1, ast.LogicOr, 1, 1},
   317  		{0, ast.LogicOr, 0, 0},
   318  		{1, ast.LogicXor, 0, 1},
   319  		{1, ast.LogicXor, 1, 0},
   320  		{0, ast.LogicXor, 0, 0},
   321  		{0, ast.LogicXor, 1, 1},
   322  	}
   323  	for _, t := range tbl {
   324  		fc := funcs[t.op]
   325  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   326  		c.Assert(err, IsNil)
   327  		v, err := evalBuiltinFunc(f, chunk.Row{})
   328  		c.Assert(err, IsNil)
   329  		switch x := t.ret.(type) {
   330  		case nil:
   331  			c.Assert(v.HoTT(), Equals, types.HoTTNull)
   332  		case int:
   333  			c.Assert(v, solitonutil.CausetEquals, types.NewCauset(int64(x)))
   334  		}
   335  	}
   336  }
   337  
   338  func (s *testEvaluatorSuite) TestBinopBitop(c *C) {
   339  	tbl := []struct {
   340  		lhs interface{}
   341  		op  string
   342  		rhs interface{}
   343  		ret interface{}
   344  	}{
   345  		{1, ast.And, 1, 1},
   346  		{1, ast.Or, 1, 1},
   347  		{1, ast.Xor, 1, 0},
   348  		{1, ast.LeftShift, 1, 2},
   349  		{2, ast.RightShift, 1, 1},
   350  		{nil, ast.And, 1, nil},
   351  		{1, ast.And, nil, nil},
   352  		{nil, ast.Or, 1, nil},
   353  		{nil, ast.Xor, 1, nil},
   354  		{nil, ast.LeftShift, 1, nil},
   355  		{nil, ast.RightShift, 1, nil},
   356  	}
   357  
   358  	for _, t := range tbl {
   359  		fc := funcs[t.op]
   360  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   361  		c.Assert(err, IsNil)
   362  		v, err := evalBuiltinFunc(f, chunk.Row{})
   363  		c.Assert(err, IsNil)
   364  
   365  		switch x := t.ret.(type) {
   366  		case nil:
   367  			c.Assert(v.HoTT(), Equals, types.HoTTNull)
   368  		case int:
   369  			c.Assert(v, solitonutil.CausetEquals, types.NewCauset(uint64(x)))
   370  		}
   371  	}
   372  }
   373  
   374  func (s *testEvaluatorSuite) TestBinopNumeric(c *C) {
   375  	tbl := []struct {
   376  		lhs interface{}
   377  		op  string
   378  		rhs interface{}
   379  		ret interface{}
   380  	}{
   381  		// plus
   382  		{1, ast.Plus, 1, 2},
   383  		{1, ast.Plus, uint64(1), 2},
   384  		{1, ast.Plus, "1", 2},
   385  		{1, ast.Plus, types.NewDecFromInt(1), 2},
   386  		{uint64(1), ast.Plus, 1, 2},
   387  		{uint64(1), ast.Plus, uint64(1), 2},
   388  		{uint64(1), ast.Plus, -1, 0},
   389  		{1, ast.Plus, []byte("1"), 2},
   390  		{1, ast.Plus, types.NewBinaryLiteralFromUint(1, -1), 2},
   391  		{1, ast.Plus, types.Enum{Name: "a", Value: 1}, 2},
   392  		{1, ast.Plus, types.Set{Name: "a", Value: 1}, 2},
   393  
   394  		// minus
   395  		{1, ast.Minus, 1, 0},
   396  		{1, ast.Minus, uint64(1), 0},
   397  		{1, ast.Minus, float64(1), 0},
   398  		{1, ast.Minus, types.NewDecFromInt(1), 0},
   399  		{uint64(1), ast.Minus, 1, 0},
   400  		{uint64(1), ast.Minus, uint64(1), 0},
   401  		{types.NewDecFromInt(1), ast.Minus, 1, 0},
   402  		{"1", ast.Minus, []byte("1"), 0},
   403  
   404  		// mul
   405  		{1, ast.Mul, 1, 1},
   406  		{1, ast.Mul, uint64(1), 1},
   407  		{1, ast.Mul, float64(1), 1},
   408  		{1, ast.Mul, types.NewDecFromInt(1), 1},
   409  		{uint64(1), ast.Mul, 1, 1},
   410  		{uint64(1), ast.Mul, uint64(1), 1},
   411  		{types.NewTime(types.FromDate(0, 0, 0, 0, 0, 0, 0), 0, 0), ast.Mul, 0, 0},
   412  		{types.ZeroDuration, ast.Mul, 0, 0},
   413  		{types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 0), ast.Mul, 0, 0},
   414  		{types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 6), ast.Mul, 0, 0},
   415  		{types.Duration{Duration: 100000000, Fsp: 6}, ast.Mul, 0, 0},
   416  
   417  		// div
   418  		{1, ast.Div, float64(1), 1},
   419  		{1, ast.Div, float64(0), nil},
   420  		{1, ast.Div, 2, 0.5},
   421  		{1, ast.Div, 0, nil},
   422  
   423  		// int div
   424  		{1, ast.IntDiv, 2, 0},
   425  		{1, ast.IntDiv, uint64(2), 0},
   426  		{1, ast.IntDiv, 0, nil},
   427  		{1, ast.IntDiv, uint64(0), nil},
   428  		{uint64(1), ast.IntDiv, 2, 0},
   429  		{uint64(1), ast.IntDiv, uint64(2), 0},
   430  		{uint64(1), ast.IntDiv, 0, nil},
   431  		{uint64(1), ast.IntDiv, uint64(0), nil},
   432  		{1.0, ast.IntDiv, 2.0, 0},
   433  
   434  		// mod
   435  		{10, ast.Mod, 2, 0},
   436  		{10, ast.Mod, uint64(2), 0},
   437  		{10, ast.Mod, 0, nil},
   438  		{10, ast.Mod, uint64(0), nil},
   439  		{-10, ast.Mod, uint64(2), 0},
   440  		{uint64(10), ast.Mod, 2, 0},
   441  		{uint64(10), ast.Mod, uint64(2), 0},
   442  		{uint64(10), ast.Mod, 0, nil},
   443  		{uint64(10), ast.Mod, uint64(0), nil},
   444  		{uint64(10), ast.Mod, -2, 0},
   445  		{float64(10), ast.Mod, 2, 0},
   446  		{float64(10), ast.Mod, 0, nil},
   447  		{types.NewDecFromInt(10), ast.Mod, 2, 0},
   448  		{types.NewDecFromInt(10), ast.Mod, 0, nil},
   449  	}
   450  
   451  	for _, t := range tbl {
   452  		fc := funcs[t.op]
   453  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   454  		c.Assert(err, IsNil)
   455  		v, err := evalBuiltinFunc(f, chunk.Row{})
   456  		c.Assert(err, IsNil)
   457  		switch v.HoTT() {
   458  		case types.HoTTNull:
   459  			c.Assert(t.ret, IsNil)
   460  		default:
   461  			// we use float64 as the result type check for all.
   462  			sc := s.ctx.GetStochastikVars().StmtCtx
   463  			f, err := v.ToFloat64(sc)
   464  			c.Assert(err, IsNil)
   465  			d := types.NewCauset(t.ret)
   466  			r, err := d.ToFloat64(sc)
   467  			c.Assert(err, IsNil)
   468  			c.Assert(r, Equals, f)
   469  		}
   470  	}
   471  
   472  	testcases := []struct {
   473  		lhs interface{}
   474  		op  string
   475  		rhs interface{}
   476  	}{
   477  		// div
   478  		{1, ast.Div, float64(0)},
   479  		{1, ast.Div, 0},
   480  		// int div
   481  		{1, ast.IntDiv, 0},
   482  		{1, ast.IntDiv, uint64(0)},
   483  		{uint64(1), ast.IntDiv, 0},
   484  		{uint64(1), ast.IntDiv, uint64(0)},
   485  		// mod
   486  		{10, ast.Mod, 0},
   487  		{10, ast.Mod, uint64(0)},
   488  		{uint64(10), ast.Mod, 0},
   489  		{uint64(10), ast.Mod, uint64(0)},
   490  		{float64(10), ast.Mod, 0},
   491  		{types.NewDecFromInt(10), ast.Mod, 0},
   492  	}
   493  
   494  	oldInSelectStmt := s.ctx.GetStochastikVars().StmtCtx.InSelectStmt
   495  	s.ctx.GetStochastikVars().StmtCtx.InSelectStmt = false
   496  	oldALLEGROSQLMode := s.ctx.GetStochastikVars().ALLEGROSQLMode
   497  	s.ctx.GetStochastikVars().ALLEGROSQLMode |= allegrosql.ModeErrorForDivisionByZero
   498  	oldInInsertStmt := s.ctx.GetStochastikVars().StmtCtx.InInsertStmt
   499  	s.ctx.GetStochastikVars().StmtCtx.InInsertStmt = true
   500  	for _, t := range testcases {
   501  		fc := funcs[t.op]
   502  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   503  		c.Assert(err, IsNil)
   504  		_, err = evalBuiltinFunc(f, chunk.Row{})
   505  		c.Assert(err, NotNil)
   506  	}
   507  
   508  	oldDividedByZeroAsWarning := s.ctx.GetStochastikVars().StmtCtx.DividedByZeroAsWarning
   509  	s.ctx.GetStochastikVars().StmtCtx.DividedByZeroAsWarning = true
   510  	for _, t := range testcases {
   511  		fc := funcs[t.op]
   512  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.lhs, t.rhs)))
   513  		c.Assert(err, IsNil)
   514  		v, err := evalBuiltinFunc(f, chunk.Row{})
   515  		c.Assert(err, IsNil)
   516  		c.Assert(v.HoTT(), Equals, types.HoTTNull)
   517  	}
   518  
   519  	s.ctx.GetStochastikVars().StmtCtx.InSelectStmt = oldInSelectStmt
   520  	s.ctx.GetStochastikVars().ALLEGROSQLMode = oldALLEGROSQLMode
   521  	s.ctx.GetStochastikVars().StmtCtx.InInsertStmt = oldInInsertStmt
   522  	s.ctx.GetStochastikVars().StmtCtx.DividedByZeroAsWarning = oldDividedByZeroAsWarning
   523  }
   524  
   525  func (s *testEvaluatorSuite) TestExtract(c *C) {
   526  	str := "2011-11-11 10:10:10.123456"
   527  	tbl := []struct {
   528  		Unit   string
   529  		Expect int64
   530  	}{
   531  		{"MICROSECOND", 123456},
   532  		{"SECOND", 10},
   533  		{"MINUTE", 10},
   534  		{"HOUR", 10},
   535  		{"DAY", 11},
   536  		{"WEEK", 45},
   537  		{"MONTH", 11},
   538  		{"QUARTER", 4},
   539  		{"YEAR", 2011},
   540  		{"SECOND_MICROSECOND", 10123456},
   541  		{"MINUTE_MICROSECOND", 1010123456},
   542  		{"MINUTE_SECOND", 1010},
   543  		{"HOUR_MICROSECOND", 101010123456},
   544  		{"HOUR_SECOND", 101010},
   545  		{"HOUR_MINUTE", 1010},
   546  		{"DAY_MICROSECOND", 11101010123456},
   547  		{"DAY_SECOND", 11101010},
   548  		{"DAY_MINUTE", 111010},
   549  		{"DAY_HOUR", 1110},
   550  		{"YEAR_MONTH", 201111},
   551  	}
   552  	for _, t := range tbl {
   553  		fc := funcs[ast.Extract]
   554  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.Unit, str)))
   555  		c.Assert(err, IsNil)
   556  		v, err := evalBuiltinFunc(f, chunk.Row{})
   557  		c.Assert(err, IsNil)
   558  		c.Assert(v, solitonutil.CausetEquals, types.NewCauset(t.Expect))
   559  	}
   560  
   561  	// Test nil
   562  	fc := funcs[ast.Extract]
   563  	f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets("SECOND", nil)))
   564  	c.Assert(err, IsNil)
   565  	v, err := evalBuiltinFunc(f, chunk.Row{})
   566  	c.Assert(err, IsNil)
   567  	c.Assert(v.HoTT(), Equals, types.HoTTNull)
   568  }
   569  
   570  func (s *testEvaluatorSuite) TestUnaryOp(c *C) {
   571  	tbl := []struct {
   572  		arg    interface{}
   573  		op     string
   574  		result interface{}
   575  	}{
   576  		// test NOT.
   577  		{1, ast.UnaryNot, int64(0)},
   578  		{0, ast.UnaryNot, int64(1)},
   579  		{nil, ast.UnaryNot, nil},
   580  		{types.NewBinaryLiteralFromUint(0, -1), ast.UnaryNot, int64(1)},
   581  		{types.NewBinaryLiteralFromUint(1, -1), ast.UnaryNot, int64(0)},
   582  		{types.Enum{Name: "a", Value: 1}, ast.UnaryNot, int64(0)},
   583  		{types.Set{Name: "a", Value: 1}, ast.UnaryNot, int64(0)},
   584  
   585  		// test BitNeg.
   586  		{nil, ast.BitNeg, nil},
   587  		{-1, ast.BitNeg, uint64(0)},
   588  
   589  		// test Minus.
   590  		{nil, ast.UnaryMinus, nil},
   591  		{float64(1.0), ast.UnaryMinus, float64(-1.0)},
   592  		{int64(1), ast.UnaryMinus, int64(-1)},
   593  		{int64(1), ast.UnaryMinus, int64(-1)},
   594  		{uint64(1), ast.UnaryMinus, -int64(1)},
   595  		{"1.0", ast.UnaryMinus, -1.0},
   596  		{[]byte("1.0"), ast.UnaryMinus, -1.0},
   597  		{types.NewBinaryLiteralFromUint(1, -1), ast.UnaryMinus, -1.0},
   598  		{true, ast.UnaryMinus, int64(-1)},
   599  		{false, ast.UnaryMinus, int64(0)},
   600  		{types.Enum{Name: "a", Value: 1}, ast.UnaryMinus, -1.0},
   601  		{types.Set{Name: "a", Value: 1}, ast.UnaryMinus, -1.0},
   602  	}
   603  	for i, t := range tbl {
   604  		fc := funcs[t.op]
   605  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.arg)))
   606  		c.Assert(err, IsNil)
   607  		result, err := evalBuiltinFunc(f, chunk.Row{})
   608  		c.Assert(err, IsNil)
   609  		c.Assert(result, solitonutil.CausetEquals, types.NewCauset(t.result), Commentf("%d", i))
   610  	}
   611  
   612  	tbl = []struct {
   613  		arg    interface{}
   614  		op     string
   615  		result interface{}
   616  	}{
   617  		{types.NewDecFromInt(1), ast.UnaryMinus, types.NewDecFromInt(-1)},
   618  		{types.ZeroDuration, ast.UnaryMinus, new(types.MyDecimal)},
   619  		{types.NewTime(types.FromGoTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), allegrosql.TypeDatetime, 0), ast.UnaryMinus, types.NewDecFromInt(-20091110230000)},
   620  	}
   621  
   622  	for _, t := range tbl {
   623  		fc := funcs[t.op]
   624  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(t.arg)))
   625  		c.Assert(err, IsNil)
   626  		c.Assert(f, NotNil)
   627  		result, err := evalBuiltinFunc(f, chunk.Row{})
   628  		c.Assert(err, IsNil)
   629  
   630  		expect := types.NewCauset(t.result)
   631  		ret, err := result.CompareCauset(s.ctx.GetStochastikVars().StmtCtx, &expect)
   632  		c.Assert(err, IsNil)
   633  		c.Assert(ret, Equals, 0, Commentf("%v %s", t.arg, t.op))
   634  	}
   635  }
   636  
   637  func (s *testEvaluatorSuite) TestMod(c *C) {
   638  	fc := funcs[ast.Mod]
   639  	f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(234, 10)))
   640  	c.Assert(err, IsNil)
   641  	r, err := evalBuiltinFunc(f, chunk.Row{})
   642  	c.Assert(err, IsNil)
   643  	c.Assert(r, solitonutil.CausetEquals, types.NewIntCauset(4))
   644  	f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(29, 9)))
   645  	c.Assert(err, IsNil)
   646  	r, err = evalBuiltinFunc(f, chunk.Row{})
   647  	c.Assert(err, IsNil)
   648  	c.Assert(r, solitonutil.CausetEquals, types.NewIntCauset(2))
   649  	f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(34.5, 3)))
   650  	c.Assert(err, IsNil)
   651  	r, err = evalBuiltinFunc(f, chunk.Row{})
   652  	c.Assert(err, IsNil)
   653  	c.Assert(r, solitonutil.CausetEquals, types.NewCauset(1.5))
   654  }