github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_cast_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  	"fmt"
    18  	"math"
    19  	"strconv"
    20  	"time"
    21  
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    24  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    25  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    26  	"github.com/whtcorpsinc/milevadb/types"
    27  	"github.com/whtcorpsinc/milevadb/types/json"
    28  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    29  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    30  )
    31  
    32  func (s *testEvaluatorSuite) TestCastXXX(c *C) {
    33  	ctx, sc := s.ctx, s.ctx.GetStochastikVars().StmtCtx
    34  
    35  	// Test `cast as char[(N)]` and `cast as binary[(N)]`.
    36  	originIgnoreTruncate := sc.IgnoreTruncate
    37  	originTruncateAsWarning := sc.TruncateAsWarning
    38  	sc.IgnoreTruncate = false
    39  	sc.TruncateAsWarning = true
    40  	defer func() {
    41  		sc.IgnoreTruncate = originIgnoreTruncate
    42  		sc.TruncateAsWarning = originTruncateAsWarning
    43  	}()
    44  
    45  	tp := types.NewFieldType(allegrosql.TypeString)
    46  	tp.Flen = 5
    47  
    48  	// cast(str as char(N)), N < len([]rune(str)).
    49  	// cast("你好world" as char(5))
    50  	tp.Charset = charset.CharsetUTF8
    51  	f := BuildCastFunction(ctx, &Constant{Value: types.NewCauset("你好world"), RetType: tp}, tp)
    52  	res, err := f.Eval(chunk.Event{})
    53  	c.Assert(err, IsNil)
    54  	c.Assert(res.GetString(), Equals, "你好wor")
    55  
    56  	// cast(str as char(N)), N > len([]rune(str)).
    57  	// cast("a" as char(5))
    58  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("a"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp)
    59  	res, err = f.Eval(chunk.Event{})
    60  	c.Assert(err, IsNil)
    61  	c.Assert(len(res.GetString()), Equals, 1)
    62  	c.Assert(res.GetString(), Equals, "a")
    63  
    64  	// cast(str as binary(N)), N < len(str).
    65  	// cast("你好world" as binary(5))
    66  	str := "你好world"
    67  	tp.Flag |= allegrosql.BinaryFlag
    68  	tp.Charset = charset.CharsetBin
    69  	tp.DefCauslate = charset.DefCauslationBin
    70  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset(str), RetType: types.NewFieldType(allegrosql.TypeString)}, tp)
    71  	res, err = f.Eval(chunk.Event{})
    72  	c.Assert(err, IsNil)
    73  	c.Assert(res.GetString(), Equals, str[:5])
    74  
    75  	// cast(str as binary(N)), N > len([]byte(str)).
    76  	// cast("a" as binary(5))
    77  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("a"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp)
    78  	res, err = f.Eval(chunk.Event{})
    79  	c.Assert(err, IsNil)
    80  	c.Assert(len(res.GetString()), Equals, 5)
    81  	c.Assert(res.GetString(), Equals, string([]byte{'a', 0x00, 0x00, 0x00, 0x00}))
    82  
    83  	// cast(str as binary(N)), N > len([]byte(str)).
    84  	// cast("a" as binary(4294967295))
    85  	tp.Flen = 4294967295
    86  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("a"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp)
    87  	res, err = f.Eval(chunk.Event{})
    88  	c.Assert(err, IsNil)
    89  	c.Assert(res.IsNull(), IsTrue)
    90  	warnings := sc.GetWarnings()
    91  	lastWarn := warnings[len(warnings)-1]
    92  	c.Assert(terror.ErrorEqual(errWarnAllowedPacketOverflowed, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
    93  
    94  	origSc := sc
    95  	oldInSelectStmt := sc.InSelectStmt
    96  	sc.InSelectStmt = true
    97  	defer func() {
    98  		sc.InSelectStmt = oldInSelectStmt
    99  	}()
   100  	sc.OverflowAsWarning = true
   101  
   102  	// cast('18446744073709551616' as unsigned);
   103  	tp1 := &types.FieldType{
   104  		Tp:      allegrosql.TypeLonglong,
   105  		Flag:    allegrosql.BinaryFlag,
   106  		Charset: charset.CharsetBin,
   107  		DefCauslate: charset.DefCauslationBin,
   108  		Flen:    allegrosql.MaxIntWidth,
   109  	}
   110  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("18446744073709551616"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   111  	res, err = f.Eval(chunk.Event{})
   112  	c.Assert(err, IsNil)
   113  	c.Assert(res.GetUint64() == math.MaxUint64, IsTrue)
   114  
   115  	warnings = sc.GetWarnings()
   116  	lastWarn = warnings[len(warnings)-1]
   117  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   118  
   119  	originFlag := tp1.Flag
   120  	tp1.Flag |= allegrosql.UnsignedFlag
   121  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("-1"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   122  	res, err = f.Eval(chunk.Event{})
   123  	c.Assert(err, IsNil)
   124  	c.Assert(res.GetUint64() == 18446744073709551615, IsTrue)
   125  
   126  	warnings = sc.GetWarnings()
   127  	lastWarn = warnings[len(warnings)-1]
   128  	c.Assert(terror.ErrorEqual(types.ErrCastNegIntAsUnsigned, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   129  	tp1.Flag = originFlag
   130  
   131  	previousWarnings := len(sc.GetWarnings())
   132  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("-1"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   133  	res, err = f.Eval(chunk.Event{})
   134  	c.Assert(err, IsNil)
   135  	c.Assert(res.GetInt64() == -1, IsTrue)
   136  	c.Assert(len(sc.GetWarnings()) == previousWarnings, IsTrue)
   137  
   138  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("-18446744073709551616"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   139  	res, err = f.Eval(chunk.Event{})
   140  	c.Assert(err, IsNil)
   141  	t := math.MinInt64
   142  	// 9223372036854775808
   143  	c.Assert(res.GetUint64() == uint64(t), IsTrue)
   144  
   145  	warnings = sc.GetWarnings()
   146  	lastWarn = warnings[len(warnings)-1]
   147  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   148  
   149  	// cast('125e342.83' as unsigned)
   150  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("125e342.83"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   151  	res, err = f.Eval(chunk.Event{})
   152  	c.Assert(err, IsNil)
   153  	c.Assert(res.GetUint64() == 125, IsTrue)
   154  
   155  	warnings = sc.GetWarnings()
   156  	lastWarn = warnings[len(warnings)-1]
   157  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   158  
   159  	// cast('1e9223372036854775807' as unsigned)
   160  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("1e9223372036854775807"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   161  	res, err = f.Eval(chunk.Event{})
   162  	c.Assert(err, IsNil)
   163  	c.Assert(res.GetUint64() == 1, IsTrue)
   164  
   165  	warnings = sc.GetWarnings()
   166  	lastWarn = warnings[len(warnings)-1]
   167  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   168  
   169  	// cast('18446744073709551616' as signed);
   170  	mask := ^allegrosql.UnsignedFlag
   171  	tp1.Flag &= mask
   172  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("18446744073709551616"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   173  	res, err = f.Eval(chunk.Event{})
   174  	c.Assert(err, IsNil)
   175  	c.Check(res.GetInt64(), Equals, int64(-1))
   176  
   177  	warnings = sc.GetWarnings()
   178  	lastWarn = warnings[len(warnings)-1]
   179  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   180  
   181  	// cast('18446744073709551614' as signed);
   182  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("18446744073709551614"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   183  	res, err = f.Eval(chunk.Event{})
   184  	c.Assert(err, IsNil)
   185  	c.Check(res.GetInt64(), Equals, int64(-2))
   186  
   187  	warnings = sc.GetWarnings()
   188  	lastWarn = warnings[len(warnings)-1]
   189  	c.Assert(terror.ErrorEqual(types.ErrCastAsSignedOverflow, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   190  
   191  	// cast('125e342.83' as signed)
   192  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("125e342.83"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   193  	res, err = f.Eval(chunk.Event{})
   194  	c.Assert(err, IsNil)
   195  	c.Assert(res.GetInt64() == 125, IsTrue)
   196  
   197  	warnings = sc.GetWarnings()
   198  	lastWarn = warnings[len(warnings)-1]
   199  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   200  
   201  	// cast('1e9223372036854775807' as signed)
   202  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset("1e9223372036854775807"), RetType: types.NewFieldType(allegrosql.TypeString)}, tp1)
   203  	res, err = f.Eval(chunk.Event{})
   204  	c.Assert(err, IsNil)
   205  	c.Assert(res.GetInt64() == 1, IsTrue)
   206  
   207  	warnings = sc.GetWarnings()
   208  	lastWarn = warnings[len(warnings)-1]
   209  	c.Assert(terror.ErrorEqual(types.ErrTruncatedWrongVal, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   210  
   211  	// create causet t1(s1 time);
   212  	// insert into t1 values('11:11:11');
   213  	// select cast(s1 as decimal(7, 2)) from t1;
   214  	ft := &types.FieldType{
   215  		Tp:      allegrosql.TypeNewDecimal,
   216  		Flag:    allegrosql.BinaryFlag | allegrosql.UnsignedFlag,
   217  		Charset: charset.CharsetBin,
   218  		DefCauslate: charset.DefCauslationBin,
   219  		Flen:    7,
   220  		Decimal: 2,
   221  	}
   222  	f = BuildCastFunction(ctx, &Constant{Value: timeCauset, RetType: types.NewFieldType(allegrosql.TypeDatetime)}, ft)
   223  	res, err = f.Eval(chunk.Event{})
   224  	c.Assert(err, IsNil)
   225  	resDecimal := new(types.MyDecimal)
   226  	resDecimal.FromString([]byte("99999.99"))
   227  	c.Assert(res.GetMysqlDecimal().Compare(resDecimal), Equals, 0)
   228  
   229  	warnings = sc.GetWarnings()
   230  	lastWarn = warnings[len(warnings)-1]
   231  	c.Assert(terror.ErrorEqual(types.ErrOverflow, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err))
   232  	sc = origSc
   233  
   234  	// create causet tt(a bigint unsigned);
   235  	// insert into tt values(18446744073709551615);
   236  	// select cast(a as decimal(65, 0)) from tt;
   237  	ft = &types.FieldType{
   238  		Tp:      allegrosql.TypeNewDecimal,
   239  		Flag:    allegrosql.BinaryFlag,
   240  		Charset: charset.CharsetBin,
   241  		DefCauslate: charset.DefCauslationBin,
   242  		Flen:    65,
   243  		Decimal: 0,
   244  	}
   245  	rt := types.NewFieldType(allegrosql.TypeLonglong)
   246  	rt.Flag = allegrosql.BinaryFlag | allegrosql.UnsignedFlag
   247  	f = BuildCastFunction(ctx, &Constant{Value: types.NewUintCauset(18446744073709551615), RetType: rt}, ft)
   248  	res, err = f.Eval(chunk.Event{})
   249  	c.Assert(err, IsNil)
   250  	u, err := res.GetMysqlDecimal().ToUint()
   251  	c.Assert(err, IsNil)
   252  	c.Assert(u == 18446744073709551615, IsTrue)
   253  
   254  	// cast(bad_string as decimal)
   255  	for _, s := range []string{"hello", ""} {
   256  		f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset(s), RetType: types.NewFieldType(allegrosql.TypeNewDecimal)}, tp)
   257  		res, err = f.Eval(chunk.Event{})
   258  		c.Assert(err, IsNil)
   259  	}
   260  
   261  	// cast(1234 as char(0))
   262  	tp.Flen = 0
   263  	tp.Charset = charset.CharsetUTF8
   264  	f = BuildCastFunction(ctx, &Constant{Value: types.NewCauset(1234), RetType: types.NewFieldType(allegrosql.TypeString)}, tp)
   265  	res, err = f.Eval(chunk.Event{})
   266  	c.Assert(err, IsNil)
   267  	c.Assert(len(res.GetString()), Equals, 0)
   268  	c.Assert(res.GetString(), Equals, "")
   269  }
   270  
   271  var (
   272  	year, month, day     = time.Now().In(time.UTC).Date()
   273  	curDateInt           = int64(year*10000 + int(month)*100 + day)
   274  	curTimeInt           = curDateInt*1000000 + 125959
   275  	curTimeWithFspReal   = float64(curTimeInt) + 0.555
   276  	curTimeString        = fmt.Sprintf("%4d-%02d-%02d 12:59:59", year, int(month), day)
   277  	curTimeWithFspString = fmt.Sprintf("%4d-%02d-%02d 12:59:59.555000", year, int(month), day)
   278  	tm                   = types.NewTime(types.FromDate(year, int(month), day, 12, 59, 59, 0), allegrosql.TypeDatetime, types.DefaultFsp)
   279  	tmWithFsp            = types.NewTime(types.FromDate(year, int(month), day, 12, 59, 59, 555000), allegrosql.TypeDatetime, types.MaxFsp)
   280  	// timeCauset indicates datetime "curYear-curMonth-curDay 12:59:59".
   281  	timeCauset = types.NewCauset(tm)
   282  	// timeWithFsFIDelatum indicates datetime "curYear-curMonth-curDay 12:59:59.555000".
   283  	timeWithFsFIDelatum = types.NewCauset(tmWithFsp)
   284  	duration         = types.Duration{
   285  		Duration: 12*time.Hour + 59*time.Minute + 59*time.Second,
   286  		Fsp:      types.DefaultFsp}
   287  	// durationCauset indicates duration "12:59:59".
   288  	durationCauset   = types.NewCauset(duration)
   289  	durationWithFsp = types.Duration{
   290  		Duration: 12*time.Hour + 59*time.Minute + 59*time.Second + 555*time.Millisecond,
   291  		Fsp:      3}
   292  	// durationWithFsFIDelatum indicates duration "12:59:59.555"
   293  	durationWithFsFIDelatum = types.NewCauset(durationWithFsp)
   294  	dt                   = types.NewTime(types.FromDate(year, int(month), day, 0, 0, 0, 0), allegrosql.TypeDate, types.DefaultFsp)
   295  
   296  	// jsonInt indicates json(3)
   297  	jsonInt = types.NewCauset(json.CreateBinary(int64(3)))
   298  
   299  	// jsonTime indicates "CURRENT_DAY 12:59:59"
   300  	jsonTime = types.NewCauset(json.CreateBinary(tm.String()))
   301  
   302  	// jsonDuration indicates
   303  	jsonDuration = types.NewCauset(json.CreateBinary(duration.String()))
   304  )
   305  
   306  func (s *testEvaluatorSuite) TestCastFuncSig(c *C) {
   307  	ctx, sc := s.ctx, s.ctx.GetStochastikVars().StmtCtx
   308  	originIgnoreTruncate := sc.IgnoreTruncate
   309  	originTZ := sc.TimeZone
   310  	sc.IgnoreTruncate = true
   311  	sc.TimeZone = time.UTC
   312  	defer func() {
   313  		sc.IgnoreTruncate = originIgnoreTruncate
   314  		sc.TimeZone = originTZ
   315  	}()
   316  	var sig builtinFunc
   317  
   318  	durationDeferredCauset := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0}
   319  	durationDeferredCauset.RetType.Decimal = int(types.DefaultFsp)
   320  	// Test cast as Decimal.
   321  	castToDecCases := []struct {
   322  		before *DeferredCauset
   323  		after  *types.MyDecimal
   324  		event    chunk.MutEvent
   325  	}{
   326  		// cast int as decimal.
   327  		{
   328  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   329  			types.NewDecFromInt(1),
   330  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(1)}),
   331  		},
   332  		// cast string as decimal.
   333  		{
   334  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   335  			types.NewDecFromInt(1),
   336  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1")}),
   337  		},
   338  		// cast real as decimal.
   339  		{
   340  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   341  			types.NewDecFromInt(1),
   342  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(1)}),
   343  		},
   344  		// cast Time as decimal.
   345  		{
   346  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   347  			types.NewDecFromInt(curTimeInt),
   348  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   349  		},
   350  		// cast Duration as decimal.
   351  		{
   352  			durationDeferredCauset,
   353  			types.NewDecFromInt(125959),
   354  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   355  		},
   356  	}
   357  	for i, t := range castToDecCases {
   358  		args := []Expression{t.before}
   359  		b, err := newBaseBuiltinFunc(ctx, "", args, 0)
   360  		c.Assert(err, IsNil)
   361  		decFunc := newBaseBuiltinCastFunc(b, false)
   362  		decFunc.tp = types.NewFieldType(allegrosql.TypeNewDecimal)
   363  		switch i {
   364  		case 0:
   365  			sig = &builtinCastIntAsDecimalSig{decFunc}
   366  		case 1:
   367  			sig = &builtinCastStringAsDecimalSig{decFunc}
   368  		case 2:
   369  			sig = &builtinCastRealAsDecimalSig{decFunc}
   370  		case 3:
   371  			sig = &builtinCastTimeAsDecimalSig{decFunc}
   372  		case 4:
   373  			sig = &builtinCastDurationAsDecimalSig{decFunc}
   374  		case 5:
   375  			sig = &builtinCastDecimalAsDecimalSig{decFunc}
   376  		}
   377  		res, isNull, err := sig.evalDecimal(t.event.ToEvent())
   378  		c.Assert(isNull, Equals, false)
   379  		c.Assert(err, IsNil)
   380  		c.Assert(res.Compare(t.after), Equals, 0)
   381  	}
   382  
   383  	durationDeferredCauset.RetType.Decimal = 1
   384  	castToDecCases2 := []struct {
   385  		before  *DeferredCauset
   386  		flen    int
   387  		decimal int
   388  		after   *types.MyDecimal
   389  		event     chunk.MutEvent
   390  	}{
   391  		// cast int as decimal.
   392  		{
   393  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   394  			7,
   395  			3,
   396  			types.NewDecFromStringForTest("1234.000"),
   397  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(1234)}),
   398  		},
   399  		// cast string as decimal.
   400  		{
   401  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   402  			7,
   403  			3,
   404  			types.NewDecFromStringForTest("1234.000"),
   405  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1234")}),
   406  		},
   407  		// cast real as decimal.
   408  		{
   409  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   410  			8,
   411  			4,
   412  			types.NewDecFromStringForTest("1234.1230"),
   413  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(1234.123)}),
   414  		},
   415  		// cast Time as decimal.
   416  		{
   417  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   418  			15,
   419  			1,
   420  			types.NewDecFromStringForTest(strconv.FormatInt(curTimeInt, 10) + ".0"),
   421  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   422  		},
   423  		// cast Duration as decimal.
   424  		{
   425  			durationDeferredCauset,
   426  			7,
   427  			1,
   428  			types.NewDecFromStringForTest("125959.0"),
   429  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   430  		},
   431  		// cast decimal as decimal.
   432  		{
   433  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   434  			7,
   435  			3,
   436  			types.NewDecFromStringForTest("1234.000"),
   437  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromStringForTest("1234"))}),
   438  		},
   439  	}
   440  
   441  	for i, t := range castToDecCases2 {
   442  		args := []Expression{t.before}
   443  		tp := types.NewFieldType(allegrosql.TypeNewDecimal)
   444  		tp.Flen, tp.Decimal = t.flen, t.decimal
   445  		b, err := newBaseBuiltinFunc(ctx, "", args, 0)
   446  		c.Assert(err, IsNil)
   447  		decFunc := newBaseBuiltinCastFunc(b, false)
   448  		decFunc.tp = tp
   449  		switch i {
   450  		case 0:
   451  			sig = &builtinCastIntAsDecimalSig{decFunc}
   452  		case 1:
   453  			sig = &builtinCastStringAsDecimalSig{decFunc}
   454  		case 2:
   455  			sig = &builtinCastRealAsDecimalSig{decFunc}
   456  		case 3:
   457  			sig = &builtinCastTimeAsDecimalSig{decFunc}
   458  		case 4:
   459  			sig = &builtinCastDurationAsDecimalSig{decFunc}
   460  		case 5:
   461  			sig = &builtinCastDecimalAsDecimalSig{decFunc}
   462  		}
   463  		res, isNull, err := sig.evalDecimal(t.event.ToEvent())
   464  		c.Assert(isNull, Equals, false)
   465  		c.Assert(err, IsNil)
   466  		c.Assert(res.ToString(), DeepEquals, t.after.ToString())
   467  	}
   468  
   469  	durationDeferredCauset.RetType.Decimal = 0
   470  	// Test cast as int.
   471  	castToIntCases := []struct {
   472  		before *DeferredCauset
   473  		after  int64
   474  		event    chunk.MutEvent
   475  	}{
   476  		// cast string as int.
   477  		{
   478  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   479  			1,
   480  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1")}),
   481  		},
   482  		// cast decimal as int.
   483  		{
   484  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   485  			1,
   486  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(1))}),
   487  		},
   488  		// cast real as int.
   489  		{
   490  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   491  			1,
   492  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(1)}),
   493  		},
   494  		// cast Time as int.
   495  		{
   496  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   497  			curTimeInt,
   498  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   499  		},
   500  		// cast Duration as int.
   501  		{
   502  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   503  			125959,
   504  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   505  		},
   506  		// cast JSON as int.
   507  		{
   508  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0},
   509  			3,
   510  			chunk.MutEventFromCausets([]types.Causet{jsonInt}),
   511  		},
   512  	}
   513  	for i, t := range castToIntCases {
   514  		args := []Expression{t.before}
   515  		b, err := newBaseBuiltinFunc(ctx, "", args, 0)
   516  		c.Assert(err, IsNil)
   517  		intFunc := newBaseBuiltinCastFunc(b, false)
   518  		switch i {
   519  		case 0:
   520  			sig = &builtinCastStringAsIntSig{intFunc}
   521  		case 1:
   522  			sig = &builtinCastDecimalAsIntSig{intFunc}
   523  		case 2:
   524  			sig = &builtinCastRealAsIntSig{intFunc}
   525  		case 3:
   526  			sig = &builtinCastTimeAsIntSig{intFunc}
   527  		case 4:
   528  			sig = &builtinCastDurationAsIntSig{intFunc}
   529  		case 5:
   530  			sig = &builtinCastJSONAsIntSig{intFunc}
   531  		}
   532  		res, isNull, err := sig.evalInt(t.event.ToEvent())
   533  		c.Assert(isNull, Equals, false)
   534  		c.Assert(err, IsNil)
   535  		c.Assert(res, Equals, t.after)
   536  	}
   537  
   538  	// Test cast as real.
   539  	castToRealCases := []struct {
   540  		before *DeferredCauset
   541  		after  float64
   542  		event    chunk.MutEvent
   543  	}{
   544  		// cast string as real.
   545  		{
   546  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   547  			1.1,
   548  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1.1")}),
   549  		},
   550  		// cast decimal as real.
   551  		{
   552  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   553  			1.1,
   554  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromFloatForTest(1.1))}),
   555  		},
   556  		// cast int as real.
   557  		{
   558  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   559  			1,
   560  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(1)}),
   561  		},
   562  		// cast Time as real.
   563  		{
   564  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   565  			float64(curTimeInt),
   566  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   567  		},
   568  		// cast Duration as real.
   569  		{
   570  			durationDeferredCauset,
   571  			125959,
   572  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   573  		},
   574  		// cast JSON as real.
   575  		{
   576  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0},
   577  			3.0,
   578  			chunk.MutEventFromCausets([]types.Causet{jsonInt}),
   579  		},
   580  	}
   581  	for i, t := range castToRealCases {
   582  		args := []Expression{t.before}
   583  		b, err := newBaseBuiltinFunc(ctx, "", args, 0)
   584  		c.Assert(err, IsNil)
   585  		realFunc := newBaseBuiltinCastFunc(b, false)
   586  		switch i {
   587  		case 0:
   588  			sig = &builtinCastStringAsRealSig{realFunc}
   589  		case 1:
   590  			sig = &builtinCastDecimalAsRealSig{realFunc}
   591  		case 2:
   592  			sig = &builtinCastIntAsRealSig{realFunc}
   593  		case 3:
   594  			sig = &builtinCastTimeAsRealSig{realFunc}
   595  		case 4:
   596  			sig = &builtinCastDurationAsRealSig{realFunc}
   597  		case 5:
   598  			sig = &builtinCastJSONAsRealSig{realFunc}
   599  		}
   600  		res, isNull, err := sig.evalReal(t.event.ToEvent())
   601  		c.Assert(isNull, Equals, false)
   602  		c.Assert(err, IsNil)
   603  		c.Assert(res, Equals, t.after)
   604  	}
   605  
   606  	// Test cast as string.
   607  	castToStringCases := []struct {
   608  		before *DeferredCauset
   609  		after  string
   610  		event    chunk.MutEvent
   611  	}{
   612  		// cast real as string.
   613  		{
   614  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   615  			"1",
   616  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(1)}),
   617  		},
   618  		// cast decimal as string.
   619  		{
   620  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   621  			"1",
   622  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(1))}),
   623  		},
   624  		// cast int as string.
   625  		{
   626  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   627  			"1",
   628  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(1)}),
   629  		},
   630  		// cast time as string.
   631  		{
   632  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   633  			curTimeString,
   634  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   635  		},
   636  		// cast duration as string.
   637  		{
   638  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   639  			"12:59:59",
   640  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   641  		},
   642  		// cast JSON as string.
   643  		{
   644  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0},
   645  			"3",
   646  			chunk.MutEventFromCausets([]types.Causet{jsonInt}),
   647  		},
   648  		// cast string as string.
   649  		{
   650  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   651  			"1234",
   652  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1234")}),
   653  		},
   654  	}
   655  	for i, t := range castToStringCases {
   656  		tp := types.NewFieldType(allegrosql.TypeVarString)
   657  		tp.Charset = charset.CharsetBin
   658  		args := []Expression{t.before}
   659  		stringFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
   660  		c.Assert(err, IsNil)
   661  		stringFunc.tp = tp
   662  		switch i {
   663  		case 0:
   664  			sig = &builtinCastRealAsStringSig{stringFunc}
   665  		case 1:
   666  			sig = &builtinCastDecimalAsStringSig{stringFunc}
   667  		case 2:
   668  			sig = &builtinCastIntAsStringSig{stringFunc}
   669  		case 3:
   670  			sig = &builtinCastTimeAsStringSig{stringFunc}
   671  		case 4:
   672  			sig = &builtinCastDurationAsStringSig{stringFunc}
   673  		case 5:
   674  			sig = &builtinCastJSONAsStringSig{stringFunc}
   675  		case 6:
   676  			sig = &builtinCastStringAsStringSig{stringFunc}
   677  		}
   678  		res, isNull, err := sig.evalString(t.event.ToEvent())
   679  		c.Assert(isNull, Equals, false)
   680  		c.Assert(err, IsNil)
   681  		c.Assert(res, Equals, t.after)
   682  	}
   683  
   684  	// Test cast as string.
   685  	castToStringCases2 := []struct {
   686  		before *DeferredCauset
   687  		after  string
   688  		flen   int
   689  		event    chunk.MutEvent
   690  	}{
   691  		// cast real as string.
   692  		{
   693  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   694  			"123",
   695  			3,
   696  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(1234.123)}),
   697  		},
   698  		// cast decimal as string.
   699  		{
   700  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   701  			"123",
   702  			3,
   703  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromStringForTest("1234.123"))}),
   704  		},
   705  		// cast int as string.
   706  		{
   707  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   708  			"123",
   709  			3,
   710  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(1234)}),
   711  		},
   712  		// cast time as string.
   713  		{
   714  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   715  			curTimeString[:3],
   716  			3,
   717  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   718  		},
   719  		// cast duration as string.
   720  		{
   721  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   722  			"12:",
   723  			3,
   724  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   725  		},
   726  		// cast string as string.
   727  		{
   728  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   729  			"你好w",
   730  			3,
   731  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("你好world")}),
   732  		},
   733  	}
   734  	for i, t := range castToStringCases2 {
   735  		args := []Expression{t.before}
   736  		tp := types.NewFieldType(allegrosql.TypeVarString)
   737  		tp.Flen, tp.Charset = t.flen, charset.CharsetBin
   738  		stringFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
   739  		c.Assert(err, IsNil)
   740  		stringFunc.tp = tp
   741  		switch i {
   742  		case 0:
   743  			sig = &builtinCastRealAsStringSig{stringFunc}
   744  		case 1:
   745  			sig = &builtinCastDecimalAsStringSig{stringFunc}
   746  		case 2:
   747  			sig = &builtinCastIntAsStringSig{stringFunc}
   748  		case 3:
   749  			sig = &builtinCastTimeAsStringSig{stringFunc}
   750  		case 4:
   751  			sig = &builtinCastDurationAsStringSig{stringFunc}
   752  		case 5:
   753  			stringFunc.tp.Charset = charset.CharsetUTF8
   754  			sig = &builtinCastStringAsStringSig{stringFunc}
   755  		}
   756  		res, isNull, err := sig.evalString(t.event.ToEvent())
   757  		c.Assert(isNull, Equals, false)
   758  		c.Assert(err, IsNil)
   759  		c.Assert(res, Equals, t.after)
   760  	}
   761  
   762  	castToTimeCases := []struct {
   763  		before *DeferredCauset
   764  		after  types.Time
   765  		event    chunk.MutEvent
   766  	}{
   767  		// cast real as Time.
   768  		{
   769  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   770  			tm,
   771  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(float64(curTimeInt))}),
   772  		},
   773  		// cast decimal as Time.
   774  		{
   775  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   776  			tm,
   777  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(curTimeInt))}),
   778  		},
   779  		// cast int as Time.
   780  		{
   781  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   782  			tm,
   783  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(curTimeInt)}),
   784  		},
   785  		// cast string as Time.
   786  		{
   787  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   788  			tm,
   789  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset(curTimeString)}),
   790  		},
   791  		// cast Duration as Time.
   792  		{
   793  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   794  			tm,
   795  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   796  		},
   797  		// cast JSON as Time.
   798  		{
   799  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0},
   800  			tm,
   801  			chunk.MutEventFromCausets([]types.Causet{jsonTime}),
   802  		},
   803  		// cast Time as Time.
   804  		{
   805  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   806  			tm,
   807  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   808  		},
   809  	}
   810  	for i, t := range castToTimeCases {
   811  		args := []Expression{t.before}
   812  		tp := types.NewFieldType(allegrosql.TypeDatetime)
   813  		tp.Decimal = int(types.DefaultFsp)
   814  		timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
   815  		c.Assert(err, IsNil)
   816  		timeFunc.tp = tp
   817  		switch i {
   818  		case 0:
   819  			sig = &builtinCastRealAsTimeSig{timeFunc}
   820  		case 1:
   821  			sig = &builtinCastDecimalAsTimeSig{timeFunc}
   822  		case 2:
   823  			sig = &builtinCastIntAsTimeSig{timeFunc}
   824  		case 3:
   825  			sig = &builtinCastStringAsTimeSig{timeFunc}
   826  		case 4:
   827  			sig = &builtinCastDurationAsTimeSig{timeFunc}
   828  		case 5:
   829  			sig = &builtinCastJSONAsTimeSig{timeFunc}
   830  		case 6:
   831  			sig = &builtinCastTimeAsTimeSig{timeFunc}
   832  		}
   833  		res, isNull, err := sig.evalTime(t.event.ToEvent())
   834  		c.Assert(err, IsNil)
   835  		c.Assert(isNull, Equals, false)
   836  		c.Assert(res.String(), Equals, t.after.String())
   837  	}
   838  
   839  	castToTimeCases2 := []struct {
   840  		before *DeferredCauset
   841  		after  types.Time
   842  		fsp    int8
   843  		tp     byte
   844  		event    chunk.MutEvent
   845  	}{
   846  		// cast real as Time(0).
   847  		{
   848  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   849  			dt,
   850  			types.DefaultFsp,
   851  			allegrosql.TypeDate,
   852  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(float64(curTimeInt))}),
   853  		},
   854  		// cast decimal as Date.
   855  		{
   856  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   857  			dt,
   858  			types.DefaultFsp,
   859  			allegrosql.TypeDate,
   860  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(curTimeInt))}),
   861  		},
   862  		// cast int as Datetime(6).
   863  		{
   864  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   865  			tm,
   866  			types.MaxFsp,
   867  			allegrosql.TypeDatetime,
   868  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(curTimeInt)}),
   869  		},
   870  		// cast string as Datetime(6).
   871  		{
   872  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   873  			tm,
   874  			types.MaxFsp,
   875  			allegrosql.TypeDatetime,
   876  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset(curTimeString)}),
   877  		},
   878  		// cast Duration as Date.
   879  		{
   880  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   881  			dt,
   882  			types.DefaultFsp,
   883  			allegrosql.TypeDate,
   884  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   885  		},
   886  		// cast Time as Date.
   887  		{
   888  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   889  			dt,
   890  			types.DefaultFsp,
   891  			allegrosql.TypeDate,
   892  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   893  		},
   894  	}
   895  	for i, t := range castToTimeCases2 {
   896  		args := []Expression{t.before}
   897  		tp := types.NewFieldType(t.tp)
   898  		tp.Decimal = int(t.fsp)
   899  		timeFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
   900  		c.Assert(err, IsNil)
   901  		timeFunc.tp = tp
   902  		switch i {
   903  		case 0:
   904  			sig = &builtinCastRealAsTimeSig{timeFunc}
   905  		case 1:
   906  			sig = &builtinCastDecimalAsTimeSig{timeFunc}
   907  		case 2:
   908  			sig = &builtinCastIntAsTimeSig{timeFunc}
   909  		case 3:
   910  			sig = &builtinCastStringAsTimeSig{timeFunc}
   911  		case 4:
   912  			sig = &builtinCastDurationAsTimeSig{timeFunc}
   913  		case 5:
   914  			sig = &builtinCastTimeAsTimeSig{timeFunc}
   915  		}
   916  		res, isNull, err := sig.evalTime(t.event.ToEvent())
   917  		c.Assert(isNull, Equals, false)
   918  		c.Assert(err, IsNil)
   919  		resAfter := t.after.String()
   920  		if t.fsp > 0 {
   921  			resAfter += "."
   922  			for i := 0; i < int(t.fsp); i++ {
   923  				resAfter += "0"
   924  			}
   925  		}
   926  		c.Assert(res.String(), Equals, resAfter)
   927  	}
   928  
   929  	castToDurationCases := []struct {
   930  		before *DeferredCauset
   931  		after  types.Duration
   932  		event    chunk.MutEvent
   933  	}{
   934  		// cast real as Duration.
   935  		{
   936  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
   937  			duration,
   938  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(125959)}),
   939  		},
   940  		// cast decimal as Duration.
   941  		{
   942  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
   943  			duration,
   944  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(125959))}),
   945  		},
   946  		// cast int as Duration.
   947  		{
   948  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
   949  			duration,
   950  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(125959)}),
   951  		},
   952  		// cast string as Duration.
   953  		{
   954  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
   955  			duration,
   956  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("12:59:59")}),
   957  		},
   958  		// cast Time as Duration.
   959  		{
   960  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
   961  			duration,
   962  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
   963  		},
   964  		// cast JSON as Duration.
   965  		{
   966  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0},
   967  			duration,
   968  			chunk.MutEventFromCausets([]types.Causet{jsonDuration}),
   969  		},
   970  		// cast Duration as Duration.
   971  		{
   972  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
   973  			duration,
   974  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
   975  		},
   976  	}
   977  	for i, t := range castToDurationCases {
   978  		args := []Expression{t.before}
   979  		tp := types.NewFieldType(allegrosql.TypeDuration)
   980  		tp.Decimal = int(types.DefaultFsp)
   981  		durationFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
   982  		c.Assert(err, IsNil)
   983  		durationFunc.tp = tp
   984  		switch i {
   985  		case 0:
   986  			sig = &builtinCastRealAsDurationSig{durationFunc}
   987  		case 1:
   988  			sig = &builtinCastDecimalAsDurationSig{durationFunc}
   989  		case 2:
   990  			sig = &builtinCastIntAsDurationSig{durationFunc}
   991  		case 3:
   992  			sig = &builtinCastStringAsDurationSig{durationFunc}
   993  		case 4:
   994  			sig = &builtinCastTimeAsDurationSig{durationFunc}
   995  		case 5:
   996  			sig = &builtinCastJSONAsDurationSig{durationFunc}
   997  		case 6:
   998  			sig = &builtinCastDurationAsDurationSig{durationFunc}
   999  		}
  1000  		res, isNull, err := sig.evalDuration(t.event.ToEvent())
  1001  		c.Assert(isNull, Equals, false)
  1002  		c.Assert(err, IsNil)
  1003  		c.Assert(res.String(), Equals, t.after.String())
  1004  	}
  1005  
  1006  	castToDurationCases2 := []struct {
  1007  		before *DeferredCauset
  1008  		after  types.Duration
  1009  		event    chunk.MutEvent
  1010  		fsp    int
  1011  	}{
  1012  		// cast real as Duration.
  1013  		{
  1014  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
  1015  			duration,
  1016  			chunk.MutEventFromCausets([]types.Causet{types.NewFloat64Causet(125959)}),
  1017  			1,
  1018  		},
  1019  		// cast decimal as Duration.
  1020  		{
  1021  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
  1022  			duration,
  1023  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromInt(125959))}),
  1024  			2,
  1025  		},
  1026  		// cast int as Duration.
  1027  		{
  1028  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLonglong), Index: 0},
  1029  			duration,
  1030  			chunk.MutEventFromCausets([]types.Causet{types.NewIntCauset(125959)}),
  1031  			3,
  1032  		},
  1033  		// cast string as Duration.
  1034  		{
  1035  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0},
  1036  			duration,
  1037  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("12:59:59")}),
  1038  			4,
  1039  		},
  1040  		// cast Time as Duration.
  1041  		{
  1042  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
  1043  			duration,
  1044  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
  1045  			5,
  1046  		},
  1047  		// cast Duration as Duration.
  1048  		{
  1049  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0},
  1050  			duration,
  1051  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
  1052  			6,
  1053  		},
  1054  	}
  1055  	for i, t := range castToDurationCases2 {
  1056  		args := []Expression{t.before}
  1057  		tp := types.NewFieldType(allegrosql.TypeDuration)
  1058  		tp.Decimal = t.fsp
  1059  		durationFunc, err := newBaseBuiltinFunc(ctx, "", args, 0)
  1060  		c.Assert(err, IsNil)
  1061  		durationFunc.tp = tp
  1062  		switch i {
  1063  		case 0:
  1064  			sig = &builtinCastRealAsDurationSig{durationFunc}
  1065  		case 1:
  1066  			sig = &builtinCastDecimalAsDurationSig{durationFunc}
  1067  		case 2:
  1068  			sig = &builtinCastIntAsDurationSig{durationFunc}
  1069  		case 3:
  1070  			sig = &builtinCastStringAsDurationSig{durationFunc}
  1071  		case 4:
  1072  			sig = &builtinCastTimeAsDurationSig{durationFunc}
  1073  		case 5:
  1074  			sig = &builtinCastDurationAsDurationSig{durationFunc}
  1075  		}
  1076  		res, isNull, err := sig.evalDuration(t.event.ToEvent())
  1077  		c.Assert(isNull, Equals, false)
  1078  		c.Assert(err, IsNil)
  1079  		resAfter := t.after.String()
  1080  		if t.fsp > 0 {
  1081  			resAfter += "."
  1082  			for j := 0; j < t.fsp; j++ {
  1083  				resAfter += "0"
  1084  			}
  1085  		}
  1086  		c.Assert(res.String(), Equals, resAfter)
  1087  	}
  1088  
  1089  	// null case
  1090  	args := []Expression{&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0}}
  1091  	event := chunk.MutEventFromCausets([]types.Causet{types.NewCauset(nil)})
  1092  	bf, err := newBaseBuiltinFunc(ctx, "", args, 0)
  1093  	c.Assert(err, IsNil)
  1094  	bf.tp = types.NewFieldType(allegrosql.TypeVarString)
  1095  	sig = &builtinCastRealAsStringSig{bf}
  1096  	sRes, isNull, err := sig.evalString(event.ToEvent())
  1097  	c.Assert(sRes, Equals, "")
  1098  	c.Assert(isNull, Equals, true)
  1099  	c.Assert(err, IsNil)
  1100  
  1101  	// test hybridType case.
  1102  	args = []Expression{&Constant{Value: types.NewCauset(types.Enum{Name: "a", Value: 0}), RetType: types.NewFieldType(allegrosql.TypeEnum)}}
  1103  	b, err := newBaseBuiltinFunc(ctx, "", args, 0)
  1104  	c.Assert(err, IsNil)
  1105  	sig = &builtinCastStringAsIntSig{newBaseBuiltinCastFunc(b, false)}
  1106  	iRes, isNull, err := sig.evalInt(chunk.Event{})
  1107  	c.Assert(isNull, Equals, false)
  1108  	c.Assert(err, IsNil)
  1109  	c.Assert(iRes, Equals, int64(0))
  1110  }
  1111  
  1112  func (s *testEvaluatorSuite) TestCastJSONAsDecimalSig(c *C) {
  1113  	ctx, sc := s.ctx, s.ctx.GetStochastikVars().StmtCtx
  1114  	originIgnoreTruncate := sc.IgnoreTruncate
  1115  	sc.IgnoreTruncate = true
  1116  	defer func() {
  1117  		sc.IgnoreTruncate = originIgnoreTruncate
  1118  	}()
  1119  
  1120  	defCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeJSON), Index: 0}
  1121  	b, err := newBaseBuiltinFunc(ctx, "", []Expression{defCaus}, 0)
  1122  	c.Assert(err, IsNil)
  1123  	decFunc := newBaseBuiltinCastFunc(b, false)
  1124  	decFunc.tp = types.NewFieldType(allegrosql.TypeNewDecimal)
  1125  	decFunc.tp.Flen = 60
  1126  	decFunc.tp.Decimal = 2
  1127  	sig := &builtinCastJSONAsDecimalSig{decFunc}
  1128  
  1129  	var tests = []struct {
  1130  		In  string
  1131  		Out *types.MyDecimal
  1132  	}{
  1133  		{`{}`, types.NewDecFromStringForTest("0")},
  1134  		{`[]`, types.NewDecFromStringForTest("0")},
  1135  		{`3`, types.NewDecFromStringForTest("3")},
  1136  		{`-3`, types.NewDecFromStringForTest("-3")},
  1137  		{`4.5`, types.NewDecFromStringForTest("4.5")},
  1138  		{`"1234"`, types.NewDecFromStringForTest("1234")},
  1139  		// test truncate
  1140  		{`"1234.1234"`, types.NewDecFromStringForTest("1234.12")},
  1141  		{`"1234.4567"`, types.NewDecFromStringForTest("1234.46")},
  1142  		// test big decimal
  1143  		{`"1234567890123456789012345678901234567890123456789012345"`, types.NewDecFromStringForTest("1234567890123456789012345678901234567890123456789012345")},
  1144  	}
  1145  	for _, tt := range tests {
  1146  		j, err := json.ParseBinaryFromString(tt.In)
  1147  		c.Assert(err, IsNil)
  1148  		event := chunk.MutEventFromCausets([]types.Causet{types.NewCauset(j)})
  1149  		res, isNull, err := sig.evalDecimal(event.ToEvent())
  1150  		c.Assert(isNull, Equals, false)
  1151  		c.Assert(err, IsNil)
  1152  		c.Assert(res.Compare(tt.Out), Equals, 0)
  1153  	}
  1154  }
  1155  
  1156  // TestWrapWithCastAsTypesClasses tests WrapWithCastAsInt/Real/String/Decimal.
  1157  func (s *testEvaluatorSuite) TestWrapWithCastAsTypesClasses(c *C) {
  1158  	ctx := s.ctx
  1159  
  1160  	durationDeferredCauset0 := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0}
  1161  	durationDeferredCauset0.RetType.Decimal = int(types.DefaultFsp)
  1162  	durationDeferredCauset3 := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDuration), Index: 0}
  1163  	durationDeferredCauset3.RetType.Decimal = 3
  1164  	cases := []struct {
  1165  		expr      Expression
  1166  		event       chunk.MutEvent
  1167  		intRes    int64
  1168  		realRes   float64
  1169  		decRes    *types.MyDecimal
  1170  		stringRes string
  1171  	}{
  1172  		{
  1173  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeLong), Index: 0},
  1174  			chunk.MutEventFromCausets([]types.Causet{types.NewCauset(123)}),
  1175  			123, 123, types.NewDecFromInt(123), "123",
  1176  		},
  1177  		{
  1178  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
  1179  			chunk.MutEventFromCausets([]types.Causet{types.NewCauset(123.555)}),
  1180  			124, 123.555, types.NewDecFromFloatForTest(123.555), "123.555",
  1181  		},
  1182  		{
  1183  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0},
  1184  			chunk.MutEventFromCausets([]types.Causet{types.NewCauset(123.123)}),
  1185  			123, 123.123, types.NewDecFromFloatForTest(123.123), "123.123",
  1186  		},
  1187  		{
  1188  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
  1189  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromStringForTest("123.123"))}),
  1190  			123, 123.123, types.NewDecFromFloatForTest(123.123), "123.123",
  1191  		},
  1192  		{
  1193  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Index: 0},
  1194  			chunk.MutEventFromCausets([]types.Causet{types.NewDecimalCauset(types.NewDecFromStringForTest("123.555"))}),
  1195  			124, 123.555, types.NewDecFromFloatForTest(123.555), "123.555",
  1196  		},
  1197  		{
  1198  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeVarString), Index: 0},
  1199  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("123.123")}),
  1200  			123, 123.123, types.NewDecFromStringForTest("123.123"), "123.123",
  1201  		},
  1202  		{
  1203  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
  1204  			chunk.MutEventFromCausets([]types.Causet{timeCauset}),
  1205  			curTimeInt, float64(curTimeInt), types.NewDecFromInt(curTimeInt), curTimeString,
  1206  		},
  1207  		{
  1208  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime), Index: 0},
  1209  			chunk.MutEventFromCausets([]types.Causet{timeWithFsFIDelatum}),
  1210  			curDateInt*1000000 + 130000, curTimeWithFspReal, types.NewDecFromFloatForTest(curTimeWithFspReal), curTimeWithFspString,
  1211  		},
  1212  		{
  1213  			durationDeferredCauset0,
  1214  			chunk.MutEventFromCausets([]types.Causet{durationCauset}),
  1215  			125959, 125959, types.NewDecFromFloatForTest(125959), "12:59:59",
  1216  		},
  1217  		{
  1218  			durationDeferredCauset3,
  1219  			chunk.MutEventFromCausets([]types.Causet{durationWithFsFIDelatum}),
  1220  			130000, 125959.555, types.NewDecFromFloatForTest(125959.555), "12:59:59.555",
  1221  		},
  1222  		{
  1223  			&DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeEnum), Index: 0},
  1224  			chunk.MutEventFromCausets([]types.Causet{types.NewCauset(types.Enum{Name: "a", Value: 123})}),
  1225  			123, 123, types.NewDecFromStringForTest("123"), "a",
  1226  		},
  1227  		{
  1228  			&Constant{RetType: types.NewFieldType(allegrosql.TypeVarString), Value: types.NewBinaryLiteralCauset(types.NewBinaryLiteralFromUint(0x61, -1))},
  1229  			chunk.MutEventFromCausets([]types.Causet{types.NewCauset(nil)}),
  1230  			97, 97, types.NewDecFromInt(0x61), "a",
  1231  		},
  1232  	}
  1233  	for i, t := range cases {
  1234  		// Test wrapping with CastAsInt.
  1235  		intExpr := WrapWithCastAsInt(ctx, t.expr)
  1236  		c.Assert(intExpr.GetType().EvalType(), Equals, types.ETInt)
  1237  		intRes, isNull, err := intExpr.EvalInt(ctx, t.event.ToEvent())
  1238  		c.Assert(err, IsNil, Commentf("cast[%v]: %#v", i, t))
  1239  		c.Assert(isNull, Equals, false)
  1240  		c.Assert(intRes, Equals, t.intRes)
  1241  
  1242  		// Test wrapping with CastAsReal.
  1243  		realExpr := WrapWithCastAsReal(ctx, t.expr)
  1244  		c.Assert(realExpr.GetType().EvalType(), Equals, types.ETReal)
  1245  		realRes, isNull, err := realExpr.EvalReal(ctx, t.event.ToEvent())
  1246  		c.Assert(err, IsNil)
  1247  		c.Assert(isNull, Equals, false)
  1248  		c.Assert(realRes, Equals, t.realRes, Commentf("cast[%v]: %#v", i, t))
  1249  
  1250  		// Test wrapping with CastAsDecimal.
  1251  		decExpr := WrapWithCastAsDecimal(ctx, t.expr)
  1252  		c.Assert(decExpr.GetType().EvalType(), Equals, types.ETDecimal)
  1253  		decRes, isNull, err := decExpr.EvalDecimal(ctx, t.event.ToEvent())
  1254  		c.Assert(err, IsNil, Commentf("case[%v]: %#v\n", i, t))
  1255  		c.Assert(isNull, Equals, false)
  1256  		c.Assert(decRes.Compare(t.decRes), Equals, 0, Commentf("case[%v]: %#v\n", i, t))
  1257  
  1258  		// Test wrapping with CastAsString.
  1259  		strExpr := WrapWithCastAsString(ctx, t.expr)
  1260  		c.Assert(strExpr.GetType().EvalType().IsStringHoTT(), IsTrue)
  1261  		strRes, isNull, err := strExpr.EvalString(ctx, t.event.ToEvent())
  1262  		c.Assert(err, IsNil)
  1263  		c.Assert(isNull, Equals, false)
  1264  		c.Assert(strRes, Equals, t.stringRes)
  1265  	}
  1266  
  1267  	unsignedIntExpr := &DeferredCauset{RetType: &types.FieldType{Tp: allegrosql.TypeLonglong, Flag: allegrosql.UnsignedFlag, Flen: allegrosql.MaxIntWidth, Decimal: 0}, Index: 0}
  1268  
  1269  	// test cast unsigned int as string.
  1270  	strExpr := WrapWithCastAsString(ctx, unsignedIntExpr)
  1271  	c.Assert(strExpr.GetType().EvalType().IsStringHoTT(), IsTrue)
  1272  	strRes, isNull, err := strExpr.EvalString(ctx, chunk.MutEventFromCausets([]types.Causet{types.NewUintCauset(math.MaxUint64)}).ToEvent())
  1273  	c.Assert(err, IsNil)
  1274  	c.Assert(strRes, Equals, strconv.FormatUint(math.MaxUint64, 10))
  1275  	c.Assert(isNull, Equals, false)
  1276  
  1277  	strRes, isNull, err = strExpr.EvalString(ctx, chunk.MutEventFromCausets([]types.Causet{types.NewUintCauset(1234)}).ToEvent())
  1278  	c.Assert(err, IsNil)
  1279  	c.Assert(isNull, Equals, false)
  1280  	c.Assert(strRes, Equals, strconv.FormatUint(uint64(1234), 10))
  1281  
  1282  	// test cast unsigned int as decimal.
  1283  	decExpr := WrapWithCastAsDecimal(ctx, unsignedIntExpr)
  1284  	c.Assert(decExpr.GetType().EvalType(), Equals, types.ETDecimal)
  1285  	decRes, isNull, err := decExpr.EvalDecimal(ctx, chunk.MutEventFromCausets([]types.Causet{types.NewUintCauset(uint64(1234))}).ToEvent())
  1286  	c.Assert(err, IsNil)
  1287  	c.Assert(isNull, Equals, false)
  1288  	c.Assert(decRes.Compare(types.NewDecFromUint(uint64(1234))), Equals, 0)
  1289  
  1290  	// test cast unsigned int as Time.
  1291  	timeExpr := WrapWithCastAsTime(ctx, unsignedIntExpr, types.NewFieldType(allegrosql.TypeDatetime))
  1292  	c.Assert(timeExpr.GetType().Tp, Equals, allegrosql.TypeDatetime)
  1293  	timeRes, isNull, err := timeExpr.EvalTime(ctx, chunk.MutEventFromCausets([]types.Causet{types.NewUintCauset(uint64(curTimeInt))}).ToEvent())
  1294  	c.Assert(err, IsNil)
  1295  	c.Assert(isNull, Equals, false)
  1296  	c.Assert(timeRes.Compare(tm), Equals, 0)
  1297  }
  1298  
  1299  func (s *testEvaluatorSuite) TestWrapWithCastAsTime(c *C) {
  1300  	sc := s.ctx.GetStochastikVars().StmtCtx
  1301  	save := sc.TimeZone
  1302  	sc.TimeZone = time.UTC
  1303  	defer func() {
  1304  		sc.TimeZone = save
  1305  	}()
  1306  	cases := []struct {
  1307  		expr Expression
  1308  		tp   *types.FieldType
  1309  		res  types.Time
  1310  	}{
  1311  		{
  1312  			&Constant{RetType: types.NewFieldType(allegrosql.TypeLong), Value: types.NewIntCauset(curTimeInt)},
  1313  			types.NewFieldType(allegrosql.TypeDate),
  1314  			dt,
  1315  		},
  1316  		{
  1317  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDouble), Value: types.NewFloat64Causet(float64(curTimeInt))},
  1318  			types.NewFieldType(allegrosql.TypeDatetime),
  1319  			tm,
  1320  		},
  1321  		{
  1322  			&Constant{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Value: types.NewDecimalCauset(types.NewDecFromInt(curTimeInt))},
  1323  			types.NewFieldType(allegrosql.TypeDate),
  1324  			dt,
  1325  		},
  1326  		{
  1327  			&Constant{RetType: types.NewFieldType(allegrosql.TypeVarString), Value: types.NewStringCauset(curTimeString)},
  1328  			types.NewFieldType(allegrosql.TypeDatetime),
  1329  			tm,
  1330  		},
  1331  		{
  1332  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDatetime), Value: timeCauset},
  1333  			types.NewFieldType(allegrosql.TypeDate),
  1334  			dt,
  1335  		},
  1336  		{
  1337  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDuration), Value: durationCauset},
  1338  			types.NewFieldType(allegrosql.TypeDatetime),
  1339  			tm,
  1340  		},
  1341  	}
  1342  	for d, t := range cases {
  1343  		expr := WrapWithCastAsTime(s.ctx, t.expr, t.tp)
  1344  		res, isNull, err := expr.EvalTime(s.ctx, chunk.Event{})
  1345  		c.Assert(err, IsNil)
  1346  		c.Assert(isNull, Equals, false)
  1347  		c.Assert(res.Type(), Equals, t.tp.Tp)
  1348  		c.Assert(res.Compare(t.res), Equals, 0, Commentf("case %d res = %s, expect = %s", d, res, t.res))
  1349  	}
  1350  }
  1351  
  1352  func (s *testEvaluatorSuite) TestWrapWithCastAsDuration(c *C) {
  1353  	cases := []struct {
  1354  		expr Expression
  1355  	}{
  1356  		{
  1357  			&Constant{RetType: types.NewFieldType(allegrosql.TypeLong), Value: types.NewIntCauset(125959)},
  1358  		},
  1359  		{
  1360  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDouble), Value: types.NewFloat64Causet(125959)},
  1361  		},
  1362  		{
  1363  			&Constant{RetType: types.NewFieldType(allegrosql.TypeNewDecimal), Value: types.NewDecimalCauset(types.NewDecFromInt(125959))},
  1364  		},
  1365  		{
  1366  			&Constant{RetType: types.NewFieldType(allegrosql.TypeVarString), Value: types.NewStringCauset("125959")},
  1367  		},
  1368  		{
  1369  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDatetime), Value: timeCauset},
  1370  		},
  1371  		{
  1372  			&Constant{RetType: types.NewFieldType(allegrosql.TypeDuration), Value: durationCauset},
  1373  		},
  1374  	}
  1375  	for _, t := range cases {
  1376  		expr := WrapWithCastAsDuration(s.ctx, t.expr)
  1377  		res, isNull, err := expr.EvalDuration(s.ctx, chunk.Event{})
  1378  		c.Assert(err, IsNil)
  1379  		c.Assert(isNull, Equals, false)
  1380  		c.Assert(res.Compare(duration), Equals, 0)
  1381  	}
  1382  }
  1383  
  1384  func (s *testEvaluatorSuite) TestWrapWithCastAsJSON(c *C) {
  1385  	input := &DeferredCauset{RetType: &types.FieldType{Tp: allegrosql.TypeJSON}}
  1386  	expr := WrapWithCastAsJSON(s.ctx, input)
  1387  
  1388  	output, ok := expr.(*DeferredCauset)
  1389  	c.Assert(ok, IsTrue)
  1390  	c.Assert(output, Equals, input)
  1391  }
  1392  
  1393  func (s *testEvaluatorSuite) TestCastIntAsIntVec(c *C) {
  1394  	cast, input, result := genCastIntAsInt()
  1395  	c.Assert(cast.vecEvalInt(input, result), IsNil)
  1396  	i64s := result.Int64s()
  1397  	it := chunk.NewIterator4Chunk(input)
  1398  	i := 0
  1399  	for event := it.Begin(); event != it.End(); event = it.Next() {
  1400  		v, _, err := cast.evalInt(event)
  1401  		c.Assert(err, IsNil)
  1402  		c.Assert(v, Equals, i64s[i])
  1403  		i++
  1404  	}
  1405  
  1406  	cast.inUnion = true
  1407  	cast.getRetTp().Flag |= allegrosql.UnsignedFlag
  1408  	c.Assert(cast.vecEvalInt(input, result), IsNil)
  1409  	i64s = result.Int64s()
  1410  	it = chunk.NewIterator4Chunk(input)
  1411  	i = 0
  1412  	for event := it.Begin(); event != it.End(); event = it.Next() {
  1413  		v, _, err := cast.evalInt(event)
  1414  		c.Assert(err, IsNil)
  1415  		c.Assert(v, Equals, i64s[i])
  1416  		i++
  1417  	}
  1418  }
  1419  
  1420  // for issue https://github.com/whtcorpsinc/milevadb/issues/16825
  1421  func (s *testEvaluatorSuite) TestCastStringAsDecimalSigWithUnsignedFlagInUnion(c *C) {
  1422  	defCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0}
  1423  	b, err := newBaseBuiltinFunc(mock.NewContext(), "", []Expression{defCaus}, 0)
  1424  	c.Assert(err, IsNil)
  1425  	// set `inUnion` to `true`
  1426  	decFunc := newBaseBuiltinCastFunc(b, true)
  1427  	decFunc.tp = types.NewFieldType(allegrosql.TypeNewDecimal)
  1428  	// set the `UnsignedFlag` bit
  1429  	decFunc.tp.Flag |= allegrosql.UnsignedFlag
  1430  	cast := &builtinCastStringAsDecimalSig{decFunc}
  1431  
  1432  	cases := []struct {
  1433  		event chunk.MutEvent
  1434  		res *types.MyDecimal
  1435  	}{
  1436  		// if `inUnion` is `true`, the result of cast a positive decimal string to unsigned decimal should be normal
  1437  		{
  1438  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("1")}),
  1439  			types.NewDecFromInt(1),
  1440  		},
  1441  		// if `inUnion` is `true`, the result of cast a negative decimal string to unsigned decimal should be 0
  1442  		{
  1443  			chunk.MutEventFromCausets([]types.Causet{types.NewStringCauset("-1")}),
  1444  			types.NewDecFromInt(0),
  1445  		},
  1446  	}
  1447  
  1448  	for _, t := range cases {
  1449  		res, isNull, err := cast.evalDecimal(t.event.ToEvent())
  1450  		c.Assert(isNull, Equals, false)
  1451  		c.Assert(err, IsNil)
  1452  		c.Assert(res.Compare(t.res), Equals, 0)
  1453  	}
  1454  }