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

     1  // Copyright 2016 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 xeval
    15  
    16  import (
    17  	"testing"
    18  
    19  	. "github.com/insionng/yougam/libraries/pingcap/check"
    20  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/codec"
    21  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    22  	"github.com/insionng/yougam/libraries/pingcap/tipb/go-tipb"
    23  )
    24  
    25  func TestT(t *testing.T) {
    26  	TestingT(t)
    27  }
    28  
    29  var _ = Suite(&testEvalSuite{})
    30  
    31  type testEvalSuite struct{}
    32  
    33  // TODO: add more tests.
    34  func (s *testEvalSuite) TestEval(c *C) {
    35  	colID := int64(1)
    36  	row := make(map[int64]types.Datum)
    37  	row[colID] = types.NewIntDatum(100)
    38  	xevaluator := &Evaluator{Row: row}
    39  	cases := []struct {
    40  		expr   *tipb.Expr
    41  		result types.Datum
    42  	}{
    43  		// Datums.
    44  		{
    45  			datumExpr(types.NewFloat32Datum(1.1)),
    46  			types.NewFloat32Datum(1.1),
    47  		},
    48  		{
    49  			datumExpr(types.NewFloat64Datum(1.1)),
    50  			types.NewFloat64Datum(1.1),
    51  		},
    52  		{
    53  			datumExpr(types.NewIntDatum(1)),
    54  			types.NewIntDatum(1),
    55  		},
    56  		{
    57  			datumExpr(types.NewUintDatum(1)),
    58  			types.NewUintDatum(1),
    59  		},
    60  		{
    61  			datumExpr(types.NewBytesDatum([]byte("abc"))),
    62  			types.NewBytesDatum([]byte("abc")),
    63  		},
    64  		{
    65  			datumExpr(types.NewStringDatum("abc")),
    66  			types.NewStringDatum("abc"),
    67  		},
    68  		{
    69  			datumExpr(types.Datum{}),
    70  			types.Datum{},
    71  		},
    72  		{
    73  			datumExpr(types.Datum{}),
    74  			types.Datum{},
    75  		},
    76  		{
    77  			columnExpr(1),
    78  			types.NewIntDatum(100),
    79  		},
    80  		// Comparison operations.
    81  		{
    82  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LT),
    83  			types.NewIntDatum(0),
    84  		},
    85  		{
    86  			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_LT),
    87  			types.NewIntDatum(1),
    88  		},
    89  		{
    90  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LT),
    91  			types.Datum{},
    92  		},
    93  		{
    94  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LE),
    95  			types.NewIntDatum(0),
    96  		},
    97  		{
    98  			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_LE),
    99  			types.NewIntDatum(1),
   100  		},
   101  		{
   102  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LE),
   103  			types.Datum{},
   104  		},
   105  		{
   106  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_EQ),
   107  			types.NewIntDatum(0),
   108  		},
   109  		{
   110  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_EQ),
   111  			types.NewIntDatum(1),
   112  		},
   113  		{
   114  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_EQ),
   115  			types.Datum{},
   116  		},
   117  		{
   118  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_NE),
   119  			types.NewIntDatum(0),
   120  		},
   121  		{
   122  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_NE),
   123  			types.NewIntDatum(1),
   124  		},
   125  		{
   126  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_NE),
   127  			types.Datum{},
   128  		},
   129  		{
   130  			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_GE),
   131  			types.NewIntDatum(0),
   132  		},
   133  		{
   134  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GE),
   135  			types.NewIntDatum(1),
   136  		},
   137  		{
   138  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GE),
   139  			types.Datum{},
   140  		},
   141  		{
   142  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GT),
   143  			types.NewIntDatum(0),
   144  		},
   145  		{
   146  			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_GT),
   147  			types.NewIntDatum(1),
   148  		},
   149  		{
   150  			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GT),
   151  			types.Datum{},
   152  		},
   153  		{
   154  			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_NullEQ),
   155  			types.NewIntDatum(0),
   156  		},
   157  		{
   158  			binaryExpr(types.Datum{}, types.Datum{}, tipb.ExprType_NullEQ),
   159  			types.NewIntDatum(1),
   160  		},
   161  		// Logic operation.
   162  		{
   163  			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_And),
   164  			types.NewIntDatum(0),
   165  		},
   166  		{
   167  			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_And),
   168  			types.NewIntDatum(1),
   169  		},
   170  		{
   171  			binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_And),
   172  			types.NewIntDatum(0),
   173  		},
   174  		{
   175  			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_And),
   176  			types.Datum{},
   177  		},
   178  		{
   179  			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(0), tipb.ExprType_Or),
   180  			types.NewIntDatum(0),
   181  		},
   182  		{
   183  			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_Or),
   184  			types.NewIntDatum(1),
   185  		},
   186  		{
   187  			binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_Or),
   188  			types.Datum{},
   189  		},
   190  		{
   191  			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_Or),
   192  			types.NewIntDatum(1),
   193  		},
   194  		{
   195  			binaryExpr(
   196  				binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ),
   197  				binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ),
   198  				tipb.ExprType_And),
   199  			types.NewIntDatum(1),
   200  		},
   201  		{
   202  			notExpr(datumExpr(types.NewIntDatum(1))),
   203  			types.NewIntDatum(0),
   204  		},
   205  		{
   206  			notExpr(datumExpr(types.NewIntDatum(0))),
   207  			types.NewIntDatum(1),
   208  		},
   209  		{
   210  			notExpr(datumExpr(types.Datum{})),
   211  			types.Datum{},
   212  		},
   213  	}
   214  	for _, ca := range cases {
   215  		result, err := xevaluator.Eval(ca.expr)
   216  		c.Assert(err, IsNil)
   217  		c.Assert(result.Kind(), Equals, ca.result.Kind())
   218  		cmp, err := result.CompareDatum(ca.result)
   219  		c.Assert(err, IsNil)
   220  		c.Assert(cmp, Equals, 0)
   221  	}
   222  }
   223  
   224  func binaryExpr(left, right interface{}, tp tipb.ExprType) *tipb.Expr {
   225  	expr := new(tipb.Expr)
   226  	expr.Tp = tp.Enum()
   227  	expr.Children = make([]*tipb.Expr, 2)
   228  	switch x := left.(type) {
   229  	case types.Datum:
   230  		expr.Children[0] = datumExpr(x)
   231  	case *tipb.Expr:
   232  		expr.Children[0] = x
   233  	}
   234  	switch x := right.(type) {
   235  	case types.Datum:
   236  		expr.Children[1] = datumExpr(x)
   237  	case *tipb.Expr:
   238  		expr.Children[1] = x
   239  	}
   240  	return expr
   241  }
   242  
   243  func datumExpr(d types.Datum) *tipb.Expr {
   244  	expr := new(tipb.Expr)
   245  	switch d.Kind() {
   246  	case types.KindInt64:
   247  		expr.Tp = tipb.ExprType_Int64.Enum()
   248  		expr.Val = codec.EncodeInt(nil, d.GetInt64())
   249  	case types.KindUint64:
   250  		expr.Tp = tipb.ExprType_Uint64.Enum()
   251  		expr.Val = codec.EncodeUint(nil, d.GetUint64())
   252  	case types.KindString:
   253  		expr.Tp = tipb.ExprType_String.Enum()
   254  		expr.Val = d.GetBytes()
   255  	case types.KindBytes:
   256  		expr.Tp = tipb.ExprType_Bytes.Enum()
   257  		expr.Val = d.GetBytes()
   258  	case types.KindFloat32:
   259  		expr.Tp = tipb.ExprType_Float32.Enum()
   260  		expr.Val = codec.EncodeFloat(nil, d.GetFloat64())
   261  	case types.KindFloat64:
   262  		expr.Tp = tipb.ExprType_Float64.Enum()
   263  		expr.Val = codec.EncodeFloat(nil, d.GetFloat64())
   264  	default:
   265  		expr.Tp = tipb.ExprType_Null.Enum()
   266  	}
   267  	return expr
   268  }
   269  
   270  func columnExpr(columnID int64) *tipb.Expr {
   271  	expr := new(tipb.Expr)
   272  	expr.Tp = tipb.ExprType_ColumnRef.Enum()
   273  	expr.Val = codec.EncodeInt(nil, columnID)
   274  	return expr
   275  }
   276  
   277  func likeExpr(target, pattern string) *tipb.Expr {
   278  	targetExpr := datumExpr(types.NewStringDatum(target))
   279  	patternExpr := datumExpr(types.NewStringDatum(pattern))
   280  	return &tipb.Expr{Tp: tipb.ExprType_Like.Enum(), Children: []*tipb.Expr{targetExpr, patternExpr}}
   281  }
   282  
   283  func notExpr(value interface{}) *tipb.Expr {
   284  	expr := new(tipb.Expr)
   285  	expr.Tp = tipb.ExprType_Not.Enum()
   286  	switch x := value.(type) {
   287  	case types.Datum:
   288  		expr.Children = []*tipb.Expr{datumExpr(x)}
   289  	case *tipb.Expr:
   290  		expr.Children = []*tipb.Expr{x}
   291  	}
   292  	return expr
   293  }
   294  
   295  func (s *testEvalSuite) TestLike(c *C) {
   296  	cases := []struct {
   297  		expr   *tipb.Expr
   298  		result int64
   299  	}{
   300  		{
   301  			expr:   likeExpr("a", ""),
   302  			result: 0,
   303  		},
   304  		{
   305  			expr:   likeExpr("a", "a"),
   306  			result: 1,
   307  		},
   308  		{
   309  			expr:   likeExpr("a", "b"),
   310  			result: 0,
   311  		},
   312  		{
   313  			expr:   likeExpr("aAb", "AaB"),
   314  			result: 1,
   315  		},
   316  		{
   317  			expr:   likeExpr("a", "%"),
   318  			result: 1,
   319  		},
   320  		{
   321  			expr:   likeExpr("aAD", "%d"),
   322  			result: 1,
   323  		},
   324  		{
   325  			expr:   likeExpr("aAeD", "%e"),
   326  			result: 0,
   327  		},
   328  		{
   329  			expr:   likeExpr("aAb", "Aa%"),
   330  			result: 1,
   331  		},
   332  		{
   333  			expr:   likeExpr("abAb", "Aa%"),
   334  			result: 0,
   335  		},
   336  		{
   337  			expr:   likeExpr("aAcb", "%C%"),
   338  			result: 1,
   339  		},
   340  		{
   341  			expr:   likeExpr("aAb", "%C%"),
   342  			result: 0,
   343  		},
   344  	}
   345  	ev := &Evaluator{}
   346  	for _, ca := range cases {
   347  		res, err := ev.Eval(ca.expr)
   348  		c.Check(err, IsNil)
   349  		c.Check(res.GetInt64(), Equals, ca.result)
   350  	}
   351  }
   352  
   353  func (s *testEvalSuite) TestWhereIn(c *C) {
   354  	cases := []struct {
   355  		expr   *tipb.Expr
   356  		result interface{}
   357  	}{
   358  		{
   359  			expr:   inExpr(1, 1, 2),
   360  			result: true,
   361  		},
   362  		{
   363  			expr:   inExpr(1, 1, nil),
   364  			result: true,
   365  		},
   366  		{
   367  			expr:   inExpr(1, 2, nil),
   368  			result: nil,
   369  		},
   370  		{
   371  			expr:   inExpr(nil, 1, nil),
   372  			result: nil,
   373  		},
   374  		{
   375  			expr:   inExpr(2, 1, nil),
   376  			result: nil,
   377  		},
   378  		{
   379  			expr:   inExpr(2),
   380  			result: false,
   381  		},
   382  		{
   383  			expr:   inExpr("abc", "abc", "ab"),
   384  			result: true,
   385  		},
   386  		{
   387  			expr:   inExpr("abc", "aba", "bab"),
   388  			result: false,
   389  		},
   390  	}
   391  	ev := &Evaluator{}
   392  	for _, ca := range cases {
   393  		res, err := ev.Eval(ca.expr)
   394  		c.Check(err, IsNil)
   395  		if ca.result == nil {
   396  			c.Check(res.Kind(), Equals, types.KindNull)
   397  		} else {
   398  			c.Check(res.Kind(), Equals, types.KindInt64)
   399  			if ca.result == true {
   400  				c.Check(res.GetInt64(), Equals, int64(1))
   401  			} else {
   402  				c.Check(res.GetInt64(), Equals, int64(0))
   403  			}
   404  		}
   405  	}
   406  }
   407  
   408  func inExpr(target interface{}, list ...interface{}) *tipb.Expr {
   409  	targetDatum := types.NewDatum(target)
   410  	var listDatums []types.Datum
   411  	for _, v := range list {
   412  		listDatums = append(listDatums, types.NewDatum(v))
   413  	}
   414  	types.SortDatums(listDatums)
   415  	targetExpr := datumExpr(targetDatum)
   416  	val, _ := codec.EncodeValue(nil, listDatums...)
   417  	listExpr := &tipb.Expr{Tp: tipb.ExprType_ValueList.Enum(), Val: val}
   418  	return &tipb.Expr{Tp: tipb.ExprType_In.Enum(), Children: []*tipb.Expr{targetExpr, listExpr}}
   419  }