github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/evaluator/builtin_string_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  	"errors"
    18  	"strings"
    19  	"time"
    20  
    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/util/mock"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/testutil"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    29  )
    30  
    31  func (s *testEvaluatorSuite) TestLength(c *C) {
    32  	defer testleak.AfterTest(c)()
    33  	d, err := builtinLength(types.MakeDatums([]interface{}{nil}...), nil)
    34  	c.Assert(err, IsNil)
    35  	c.Assert(d.Kind(), Equals, types.KindNull)
    36  
    37  	tbl := []struct {
    38  		Input    interface{}
    39  		Expected int64
    40  	}{
    41  		{"abc", 3},
    42  		{1, 1},
    43  		{3.14, 4},
    44  		{mysql.Time{Time: time.Now(), Fsp: 6, Type: mysql.TypeDatetime}, 26},
    45  		{mysql.Bit{Value: 1, Width: 8}, 1},
    46  		{mysql.Hex{Value: 1}, 1},
    47  		{mysql.Set{Value: 1, Name: "abc"}, 3},
    48  	}
    49  
    50  	dtbl := tblToDtbl(tbl)
    51  
    52  	for _, t := range dtbl {
    53  		d, err = builtinLength(t["Input"], nil)
    54  		c.Assert(err, IsNil)
    55  		c.Assert(d, testutil.DatumEquals, t["Expected"][0])
    56  	}
    57  }
    58  
    59  func (s *testEvaluatorSuite) TestASCII(c *C) {
    60  	defer testleak.AfterTest(c)()
    61  	v, err := builtinASCII(types.MakeDatums([]interface{}{nil}...), nil)
    62  	c.Assert(err, IsNil)
    63  	c.Assert(v.Kind(), Equals, types.KindNull)
    64  
    65  	for _, t := range []struct {
    66  		Input    interface{}
    67  		Expected int64
    68  	}{
    69  		{"", 0},
    70  		{"A", 65},
    71  		{"你好", 228},
    72  		{1, 49},
    73  		{1.2, 49},
    74  		{true, 49},
    75  		{false, 48},
    76  	} {
    77  		v, err = builtinASCII(types.MakeDatums(t.Input), nil)
    78  		c.Assert(err, IsNil)
    79  		c.Assert(v.GetInt64(), Equals, t.Expected)
    80  	}
    81  
    82  	v, err = builtinASCII(types.MakeDatums([]interface{}{errors.New("must error")}...), nil)
    83  	c.Assert(err, NotNil)
    84  }
    85  
    86  func (s *testEvaluatorSuite) TestConcat(c *C) {
    87  	defer testleak.AfterTest(c)()
    88  	args := []interface{}{nil}
    89  
    90  	v, err := builtinConcat(types.MakeDatums(args...), nil)
    91  	c.Assert(err, IsNil)
    92  	c.Assert(v.Kind(), Equals, types.KindNull)
    93  
    94  	args = []interface{}{"a", "b", "c"}
    95  	v, err = builtinConcat(types.MakeDatums(args...), nil)
    96  	c.Assert(err, IsNil)
    97  	c.Assert(v.GetString(), Equals, "abc")
    98  
    99  	args = []interface{}{"a", "b", nil, "c"}
   100  	v, err = builtinConcat(types.MakeDatums(args...), nil)
   101  	c.Assert(err, IsNil)
   102  	c.Assert(v.Kind(), Equals, types.KindNull)
   103  
   104  	args = []interface{}{errors.New("must error")}
   105  	_, err = builtinConcat(types.MakeDatums(args...), nil)
   106  	c.Assert(err, NotNil)
   107  }
   108  
   109  func (s *testEvaluatorSuite) TestConcatWS(c *C) {
   110  	defer testleak.AfterTest(c)()
   111  	args := types.MakeDatums([]interface{}{nil}...)
   112  
   113  	v, err := builtinConcatWS(args, nil)
   114  	c.Assert(err, IsNil)
   115  	c.Assert(v.Kind(), Equals, types.KindNull)
   116  
   117  	args = types.MakeDatums([]interface{}{"|", "a", nil, "b", "c"}...)
   118  
   119  	v, err = builtinConcatWS(args, nil)
   120  	c.Assert(err, IsNil)
   121  	c.Assert(v.GetString(), Equals, "a|b|c")
   122  
   123  	args = types.MakeDatums([]interface{}{errors.New("must error")}...)
   124  	_, err = builtinConcatWS(args, nil)
   125  	c.Assert(err, NotNil)
   126  }
   127  
   128  func (s *testEvaluatorSuite) TestLeft(c *C) {
   129  	defer testleak.AfterTest(c)()
   130  	args := types.MakeDatums([]interface{}{"abcdefg", int64(2)}...)
   131  	v, err := builtinLeft(args, nil)
   132  	c.Assert(err, IsNil)
   133  	c.Assert(v.GetString(), Equals, "ab")
   134  
   135  	args = types.MakeDatums([]interface{}{"abcdefg", int64(-1)}...)
   136  	v, err = builtinLeft(args, nil)
   137  	c.Assert(err, IsNil)
   138  	c.Assert(v.GetString(), Equals, "")
   139  
   140  	args = types.MakeDatums([]interface{}{"abcdefg", int64(100)}...)
   141  	v, err = builtinLeft(args, nil)
   142  	c.Assert(err, IsNil)
   143  	c.Assert(v.GetString(), Equals, "abcdefg")
   144  
   145  	args = types.MakeDatums([]interface{}{1, int64(1)}...)
   146  	_, err = builtinLeft(args, nil)
   147  	c.Assert(err, IsNil)
   148  
   149  	args = types.MakeDatums([]interface{}{"abcdefg", "xxx"}...)
   150  	_, err = builtinLeft(args, nil)
   151  	c.Assert(err, NotNil)
   152  }
   153  
   154  func (s *testEvaluatorSuite) TestRepeat(c *C) {
   155  	defer testleak.AfterTest(c)()
   156  	args := []interface{}{"a", int64(2)}
   157  	v, err := builtinRepeat(types.MakeDatums(args...), nil)
   158  	c.Assert(err, IsNil)
   159  	c.Assert(v.GetString(), Equals, "aa")
   160  
   161  	args = []interface{}{"a", uint64(2)}
   162  	v, err = builtinRepeat(types.MakeDatums(args...), nil)
   163  	c.Assert(err, IsNil)
   164  	c.Assert(v.GetString(), Equals, "aa")
   165  
   166  	args = []interface{}{"a", int64(-1)}
   167  	v, err = builtinRepeat(types.MakeDatums(args...), nil)
   168  	c.Assert(err, IsNil)
   169  	c.Assert(v.GetString(), Equals, "")
   170  
   171  	args = []interface{}{"a", int64(0)}
   172  	v, err = builtinRepeat(types.MakeDatums(args...), nil)
   173  	c.Assert(err, IsNil)
   174  	c.Assert(v.GetString(), Equals, "")
   175  
   176  	args = []interface{}{"a", uint64(0)}
   177  	v, err = builtinRepeat(types.MakeDatums(args...), nil)
   178  	c.Assert(err, IsNil)
   179  	c.Assert(v.GetString(), Equals, "")
   180  }
   181  
   182  func (s *testEvaluatorSuite) TestLowerAndUpper(c *C) {
   183  	defer testleak.AfterTest(c)()
   184  	d, err := builtinLower(types.MakeDatums([]interface{}{nil}...), nil)
   185  	c.Assert(err, IsNil)
   186  	c.Assert(d.Kind(), Equals, types.KindNull)
   187  
   188  	d, err = builtinUpper(types.MakeDatums([]interface{}{nil}...), nil)
   189  	c.Assert(err, IsNil)
   190  	c.Assert(d.Kind(), Equals, types.KindNull)
   191  
   192  	tbl := []struct {
   193  		Input  interface{}
   194  		Expect string
   195  	}{
   196  		{"abc", "abc"},
   197  		{1, "1"},
   198  	}
   199  
   200  	dtbl := tblToDtbl(tbl)
   201  
   202  	for _, t := range dtbl {
   203  		d, err = builtinLower(t["Input"], nil)
   204  		c.Assert(err, IsNil)
   205  		c.Assert(d, testutil.DatumEquals, t["Expect"][0])
   206  
   207  		d, err = builtinUpper(t["Input"], nil)
   208  		c.Assert(err, IsNil)
   209  		c.Assert(d.GetString(), Equals, strings.ToUpper(t["Expect"][0].GetString()))
   210  	}
   211  }
   212  
   213  func (s *testEvaluatorSuite) TestReverse(c *C) {
   214  	defer testleak.AfterTest(c)()
   215  	d, err := builtinReverse(types.MakeDatums([]interface{}{nil}...), nil)
   216  	c.Assert(err, IsNil)
   217  	c.Assert(d.Kind(), Equals, types.KindNull)
   218  
   219  	tbl := []struct {
   220  		Input  interface{}
   221  		Expect string
   222  	}{
   223  		{"abc", "cba"},
   224  		{"LIKE", "EKIL"},
   225  		{123, "321"},
   226  		{"", ""},
   227  	}
   228  
   229  	dtbl := tblToDtbl(tbl)
   230  
   231  	for _, t := range dtbl {
   232  		d, err = builtinReverse(t["Input"], nil)
   233  		c.Assert(err, IsNil)
   234  		c.Assert(d, testutil.DatumEquals, t["Expect"][0])
   235  	}
   236  }
   237  
   238  func (s *testEvaluatorSuite) TestStrcmp(c *C) {
   239  	defer testleak.AfterTest(c)()
   240  	tbl := []struct {
   241  		Input  []interface{}
   242  		Expect interface{}
   243  	}{
   244  		{[]interface{}{"1", "2"}, -1},
   245  		{[]interface{}{"2", "1"}, 1},
   246  		{[]interface{}{"123", "2"}, -1},
   247  		{[]interface{}{"1", "213"}, -1},
   248  		{[]interface{}{"123", "123"}, 0},
   249  		{[]interface{}{"", "123"}, -1},
   250  		{[]interface{}{"123", ""}, 1},
   251  		{[]interface{}{"", ""}, 0},
   252  		{[]interface{}{nil, "123"}, nil},
   253  		{[]interface{}{"123", nil}, nil},
   254  		{[]interface{}{nil, nil}, nil},
   255  		{[]interface{}{"", nil}, nil},
   256  		{[]interface{}{nil, ""}, nil},
   257  	}
   258  
   259  	dtbl := tblToDtbl(tbl)
   260  	for _, t := range dtbl {
   261  		d, err := builtinStrcmp(t["Input"], nil)
   262  		c.Assert(err, IsNil)
   263  		c.Assert(d, testutil.DatumEquals, t["Expect"][0])
   264  	}
   265  }
   266  
   267  func (s *testEvaluatorSuite) TestReplace(c *C) {
   268  	defer testleak.AfterTest(c)()
   269  	tbl := []struct {
   270  		Input  []interface{}
   271  		Expect interface{}
   272  	}{
   273  		{[]interface{}{nil, nil, nil}, nil},
   274  		{[]interface{}{1, nil, 2}, nil},
   275  		{[]interface{}{1, 1, nil}, nil},
   276  		{[]interface{}{"12345", 2, 222}, "1222345"},
   277  		{[]interface{}{"12325", 2, "a"}, "1a3a5"},
   278  		{[]interface{}{12345, 2, "aa"}, "1aa345"},
   279  	}
   280  
   281  	dtbl := tblToDtbl(tbl)
   282  
   283  	for _, t := range dtbl {
   284  		d, err := builtinReplace(t["Input"], nil)
   285  		c.Assert(err, IsNil)
   286  		c.Assert(d, testutil.DatumEquals, t["Expect"][0])
   287  	}
   288  }
   289  
   290  func (s *testEvaluatorSuite) TestSubstring(c *C) {
   291  	defer testleak.AfterTest(c)()
   292  
   293  	d, err := builtinSubstring(types.MakeDatums([]interface{}{"hello", 2, -1}...), nil)
   294  	c.Assert(err, IsNil)
   295  	c.Assert(d.GetString(), Equals, "")
   296  
   297  	tbl := []struct {
   298  		str    string
   299  		pos    int64
   300  		slen   int64
   301  		result string
   302  	}{
   303  		{"Quadratically", 5, -1, "ratically"},
   304  		{"foobarbar", 4, -1, "barbar"},
   305  		{"Sakila", 1, -1, "Sakila"},
   306  		{"Sakila", 2, -1, "akila"},
   307  		{"Sakila", -3, -1, "ila"},
   308  		{"Sakila", -5, 3, "aki"},
   309  		{"Sakila", -4, 2, "ki"},
   310  		{"Quadratically", 5, 6, "ratica"},
   311  		{"Sakila", 1, 4, "Saki"},
   312  		{"Sakila", -6, 4, "Saki"},
   313  		{"Sakila", 2, 1000, "akila"},
   314  		{"Sakila", -5, 1000, "akila"},
   315  		{"Sakila", 2, -2, ""},
   316  		{"Sakila", -5, -2, ""},
   317  		{"Sakila", 2, 0, ""},
   318  		{"Sakila", -5, -3, ""},
   319  		{"Sakila", -1000, 3, ""},
   320  		{"Sakila", 1000, 2, ""},
   321  		{"", 2, 3, ""},
   322  	}
   323  	ctx := mock.NewContext()
   324  	for _, v := range tbl {
   325  		f := &ast.FuncCallExpr{
   326  			FnName: model.NewCIStr("SUBSTRING"),
   327  			Args:   []ast.ExprNode{ast.NewValueExpr(v.str), ast.NewValueExpr(v.pos)},
   328  		}
   329  		if v.slen != -1 {
   330  			f.Args = append(f.Args, ast.NewValueExpr(v.slen))
   331  		}
   332  		r, err := Eval(ctx, f)
   333  		c.Assert(err, IsNil)
   334  		c.Assert(r.Kind(), Equals, types.KindString)
   335  		c.Assert(r.GetString(), Equals, v.result)
   336  
   337  		r1, err := Eval(ctx, f)
   338  		c.Assert(err, IsNil)
   339  		c.Assert(r1.Kind(), Equals, types.KindString)
   340  		c.Assert(r.GetString(), Equals, r1.GetString())
   341  	}
   342  	errTbl := []struct {
   343  		str    interface{}
   344  		pos    interface{}
   345  		len    interface{}
   346  		result string
   347  	}{
   348  		{"foobarbar", "4", -1, "barbar"},
   349  		{"Quadratically", 5, "6", "ratica"},
   350  	}
   351  	for _, v := range errTbl {
   352  		f := &ast.FuncCallExpr{
   353  			FnName: model.NewCIStr("SUBSTRING"),
   354  			Args:   []ast.ExprNode{ast.NewValueExpr(v.str), ast.NewValueExpr(v.pos)},
   355  		}
   356  		if v.len != -1 {
   357  			f.Args = append(f.Args, ast.NewValueExpr(v.len))
   358  		}
   359  		_, err := Eval(ctx, f)
   360  		c.Assert(err, NotNil)
   361  	}
   362  }
   363  
   364  func (s *testEvaluatorSuite) TestConvert(c *C) {
   365  	defer testleak.AfterTest(c)()
   366  	ctx := mock.NewContext()
   367  	tbl := []struct {
   368  		str    string
   369  		cs     string
   370  		result string
   371  	}{
   372  		{"haha", "utf8", "haha"},
   373  		{"haha", "ascii", "haha"},
   374  	}
   375  	for _, v := range tbl {
   376  		f := &ast.FuncCallExpr{
   377  			FnName: model.NewCIStr("CONVERT"),
   378  			Args: []ast.ExprNode{
   379  				ast.NewValueExpr(v.str),
   380  				ast.NewValueExpr(v.cs),
   381  			},
   382  		}
   383  
   384  		r, err := Eval(ctx, f)
   385  		c.Assert(err, IsNil)
   386  		c.Assert(r.Kind(), Equals, types.KindString)
   387  		c.Assert(r.GetString(), Equals, v.result)
   388  	}
   389  
   390  	// Test case for error
   391  	errTbl := []struct {
   392  		str    interface{}
   393  		cs     string
   394  		result string
   395  	}{
   396  		{"haha", "wrongcharset", "haha"},
   397  	}
   398  	for _, v := range errTbl {
   399  		f := &ast.FuncCallExpr{
   400  			FnName: model.NewCIStr("CONVERT"),
   401  			Args: []ast.ExprNode{
   402  				ast.NewValueExpr(v.str),
   403  				ast.NewValueExpr(v.cs),
   404  			},
   405  		}
   406  
   407  		_, err := Eval(ctx, f)
   408  		c.Assert(err, NotNil)
   409  	}
   410  }
   411  
   412  func (s *testEvaluatorSuite) TestSubstringIndex(c *C) {
   413  	defer testleak.AfterTest(c)()
   414  	tbl := []struct {
   415  		str    string
   416  		delim  string
   417  		count  int64
   418  		result string
   419  	}{
   420  		{"www.mysql.com", ".", 2, "www.mysql"},
   421  		{"www.mysql.com", ".", -2, "mysql.com"},
   422  		{"www.mysql.com", ".", 0, ""},
   423  		{"www.mysql.com", ".", 3, "www.mysql.com"},
   424  		{"www.mysql.com", ".", 4, "www.mysql.com"},
   425  		{"www.mysql.com", ".", -3, "www.mysql.com"},
   426  		{"www.mysql.com", ".", -4, "www.mysql.com"},
   427  
   428  		{"www.mysql.com", "d", 1, "www.mysql.com"},
   429  		{"www.mysql.com", "d", 0, ""},
   430  		{"www.mysql.com", "d", -1, "www.mysql.com"},
   431  
   432  		{"", ".", 2, ""},
   433  		{"", ".", -2, ""},
   434  		{"", ".", 0, ""},
   435  
   436  		{"www.mysql.com", "", 1, ""},
   437  		{"www.mysql.com", "", -1, ""},
   438  		{"www.mysql.com", "", 0, ""},
   439  	}
   440  	ctx := mock.NewContext()
   441  	for _, v := range tbl {
   442  		f := &ast.FuncCallExpr{
   443  			FnName: model.NewCIStr("SUBSTRING_INDEX"),
   444  			Args:   []ast.ExprNode{ast.NewValueExpr(v.str), ast.NewValueExpr(v.delim), ast.NewValueExpr(v.count)},
   445  		}
   446  		r, err := Eval(ctx, f)
   447  		c.Assert(err, IsNil)
   448  		c.Assert(r.Kind(), Equals, types.KindString)
   449  		c.Assert(r.GetString(), Equals, v.result)
   450  	}
   451  	errTbl := []struct {
   452  		str   interface{}
   453  		delim interface{}
   454  		count interface{}
   455  	}{
   456  		{nil, ".", 2},
   457  		{nil, ".", -2},
   458  		{nil, ".", 0},
   459  		{"asdf", nil, 2},
   460  		{"asdf", nil, -2},
   461  		{"asdf", nil, 0},
   462  		{"www.mysql.com", ".", nil},
   463  	}
   464  	for _, v := range errTbl {
   465  		f := &ast.FuncCallExpr{
   466  			FnName: model.NewCIStr("SUBSTRING_INDEX"),
   467  			Args:   []ast.ExprNode{ast.NewValueExpr(v.str), ast.NewValueExpr(v.delim), ast.NewValueExpr(v.count)},
   468  		}
   469  		r, err := Eval(ctx, f)
   470  		c.Assert(err, NotNil)
   471  		c.Assert(r.Kind(), Equals, types.KindNull)
   472  	}
   473  }
   474  
   475  func (s *testEvaluatorSuite) TestLocate(c *C) {
   476  	defer testleak.AfterTest(c)()
   477  	tbl := []struct {
   478  		subStr string
   479  		Str    string
   480  		result int64
   481  	}{
   482  		{"bar", "foobarbar", 4},
   483  		{"xbar", "foobar", 0},
   484  		{"", "foobar", 1},
   485  		{"foobar", "", 0},
   486  		{"", "", 1},
   487  	}
   488  	ctx := mock.NewContext()
   489  	for _, v := range tbl {
   490  		f := &ast.FuncCallExpr{
   491  			FnName: model.NewCIStr("LOCATE"),
   492  			Args:   []ast.ExprNode{ast.NewValueExpr(v.subStr), ast.NewValueExpr(v.Str)},
   493  		}
   494  		r, err := Eval(ctx, f)
   495  		c.Assert(err, IsNil)
   496  		c.Assert(r.Kind(), Equals, types.KindInt64)
   497  		c.Assert(r.GetInt64(), Equals, v.result)
   498  	}
   499  
   500  	tbl2 := []struct {
   501  		subStr string
   502  		Str    string
   503  		pos    int64
   504  		result int64
   505  	}{
   506  		{"bar", "foobarbar", 5, 7},
   507  		{"xbar", "foobar", 1, 0},
   508  		{"", "foobar", 2, 2},
   509  		{"foobar", "", 1, 0},
   510  		{"", "", 2, 0},
   511  	}
   512  	for _, v := range tbl2 {
   513  		f := &ast.FuncCallExpr{
   514  			FnName: model.NewCIStr("LOCATE"),
   515  			Args:   []ast.ExprNode{ast.NewValueExpr(v.subStr), ast.NewValueExpr(v.Str), ast.NewValueExpr(v.pos)},
   516  		}
   517  		r, err := Eval(ctx, f)
   518  		c.Assert(err, IsNil)
   519  		c.Assert(r.Kind(), Equals, types.KindInt64)
   520  		c.Assert(r.GetInt64(), Equals, v.result)
   521  	}
   522  
   523  	errTbl := []struct {
   524  		subStr interface{}
   525  		Str    interface{}
   526  	}{
   527  		{nil, nil},
   528  		{"", nil},
   529  		{nil, ""},
   530  		{"foo", nil},
   531  		{nil, "bar"},
   532  	}
   533  	for _, v := range errTbl {
   534  		f := &ast.FuncCallExpr{
   535  			FnName: model.NewCIStr("LOCATE"),
   536  			Args:   []ast.ExprNode{ast.NewValueExpr(v.subStr), ast.NewValueExpr(v.Str)},
   537  		}
   538  		r, _ := Eval(ctx, f)
   539  		c.Assert(r.Kind(), Equals, types.KindNull)
   540  	}
   541  
   542  	errTbl2 := []struct {
   543  		subStr interface{}
   544  		Str    interface{}
   545  		pos    interface{}
   546  	}{
   547  		{nil, nil, 1},
   548  		{"", nil, 1},
   549  		{nil, "", 1},
   550  		{"foo", nil, -1},
   551  		{nil, "bar", 0},
   552  	}
   553  	for _, v := range errTbl2 {
   554  		f := &ast.FuncCallExpr{
   555  			FnName: model.NewCIStr("LOCATE"),
   556  			Args:   []ast.ExprNode{ast.NewValueExpr(v.subStr), ast.NewValueExpr(v.Str), ast.NewValueExpr(v.pos)},
   557  		}
   558  		r, _ := Eval(ctx, f)
   559  		c.Assert(r.Kind(), Equals, types.KindNull)
   560  	}
   561  }
   562  
   563  func (s *testEvaluatorSuite) TestTrim(c *C) {
   564  	defer testleak.AfterTest(c)()
   565  	tbl := []struct {
   566  		str    interface{}
   567  		remstr interface{}
   568  		dir    ast.TrimDirectionType
   569  		result interface{}
   570  	}{
   571  		{"  bar   ", nil, ast.TrimBothDefault, "bar"},
   572  		{"xxxbarxxx", "x", ast.TrimLeading, "barxxx"},
   573  		{"xxxbarxxx", "x", ast.TrimBoth, "bar"},
   574  		{"barxxyz", "xyz", ast.TrimTrailing, "barx"},
   575  		{nil, "xyz", ast.TrimBoth, nil},
   576  		{1, 2, ast.TrimBoth, "1"},
   577  		{"  \t\rbar\n   ", nil, ast.TrimBothDefault, "bar"},
   578  	}
   579  	ctx := mock.NewContext()
   580  	for _, v := range tbl {
   581  		f := &ast.FuncCallExpr{
   582  			FnName: model.NewCIStr("TRIM"),
   583  			Args: []ast.ExprNode{
   584  				ast.NewValueExpr(v.str),
   585  				ast.NewValueExpr(v.remstr),
   586  				ast.NewValueExpr(v.dir),
   587  			},
   588  		}
   589  		r, err := Eval(ctx, f)
   590  		c.Assert(err, IsNil)
   591  		c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result))
   592  	}
   593  
   594  	for _, v := range []struct {
   595  		str, result interface{}
   596  		fn          string
   597  	}{
   598  		{"  ", "", "LTRIM"},
   599  		{"  ", "", "RTRIM"},
   600  		{"foo0", "foo0", "LTRIM"},
   601  		{"bar0", "bar0", "RTRIM"},
   602  		{"  foo1", "foo1", "LTRIM"},
   603  		{"bar1  ", "bar1", "RTRIM"},
   604  		{spaceChars + "foo2  ", "foo2  ", "LTRIM"},
   605  		{"  bar2" + spaceChars, "  bar2", "RTRIM"},
   606  		{nil, nil, "LTRIM"},
   607  		{nil, nil, "RTRIM"},
   608  	} {
   609  		f := &ast.FuncCallExpr{
   610  			FnName: model.NewCIStr(v.fn),
   611  			Args:   []ast.ExprNode{ast.NewValueExpr(v.str)},
   612  		}
   613  		r, err := Eval(ctx, f)
   614  		c.Assert(err, IsNil)
   615  		c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result))
   616  	}
   617  }