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 }