github.com/XiaoMi/Gaea@v1.2.5/parser/tidb-types/datum.go (about) 1 // Copyright 2016 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package types 15 16 import ( 17 "fmt" 18 "math" 19 "sort" 20 "strconv" 21 "strings" 22 "time" 23 "unicode/utf8" 24 25 "github.com/pingcap/errors" 26 27 "github.com/XiaoMi/Gaea/log" 28 "github.com/XiaoMi/Gaea/mysql" 29 "github.com/XiaoMi/Gaea/parser/stmtctx" 30 "github.com/XiaoMi/Gaea/parser/terror" 31 "github.com/XiaoMi/Gaea/parser/tidb-types/json" 32 "github.com/XiaoMi/Gaea/util/hack" 33 ) 34 35 // Kind constants. 36 const ( 37 KindNull byte = 0 38 KindInt64 byte = 1 39 KindUint64 byte = 2 40 KindFloat32 byte = 3 41 KindFloat64 byte = 4 42 KindString byte = 5 43 KindBytes byte = 6 44 KindBinaryLiteral byte = 7 // Used for BIT / HEX literals. 45 KindMysqlDecimal byte = 8 46 KindMysqlDuration byte = 9 47 KindMysqlEnum byte = 10 48 KindMysqlBit byte = 11 // Used for BIT table column values. 49 KindMysqlSet byte = 12 50 KindMysqlTime byte = 13 51 KindInterface byte = 14 52 KindMinNotNull byte = 15 53 KindMaxValue byte = 16 54 KindRaw byte = 17 55 KindMysqlJSON byte = 18 56 ) 57 58 // Datum is a data box holds different kind of data. 59 // It has better performance and is easier to use than `interface{}`. 60 type Datum struct { 61 k byte // datum kind. 62 collation uint8 // collation can hold uint8 values. 63 decimal uint16 // decimal can hold uint16 values. 64 length uint32 // length can hold uint32 values. 65 i int64 // i can hold int64 uint64 float64 values. 66 b []byte // b can hold string or []byte values. 67 x interface{} // x hold all other types. 68 } 69 70 // Copy deep copies a Datum. 71 func (d *Datum) Copy() *Datum { 72 ret := *d 73 if d.b != nil { 74 ret.b = make([]byte, len(d.b)) 75 copy(ret.b, d.b) 76 } 77 switch ret.Kind() { 78 case KindMysqlDecimal: 79 d := *d.GetMysqlDecimal() 80 ret.SetMysqlDecimal(&d) 81 case KindMysqlTime: 82 ret.SetMysqlTime(d.GetMysqlTime()) 83 } 84 return &ret 85 } 86 87 // Kind gets the kind of the datum. 88 func (d *Datum) Kind() byte { 89 return d.k 90 } 91 92 // Collation gets the collation of the datum. 93 func (d *Datum) Collation() byte { 94 return d.collation 95 } 96 97 // SetCollation sets the collation of the datum. 98 func (d *Datum) SetCollation(collation byte) { 99 d.collation = collation 100 } 101 102 // Frac gets the frac of the datum. 103 func (d *Datum) Frac() int { 104 return int(d.decimal) 105 } 106 107 // SetFrac sets the frac of the datum. 108 func (d *Datum) SetFrac(frac int) { 109 d.decimal = uint16(frac) 110 } 111 112 // Length gets the length of the datum. 113 func (d *Datum) Length() int { 114 return int(d.length) 115 } 116 117 // SetLength sets the length of the datum. 118 func (d *Datum) SetLength(l int) { 119 d.length = uint32(l) 120 } 121 122 // IsNull checks if datum is null. 123 func (d *Datum) IsNull() bool { 124 return d.k == KindNull 125 } 126 127 // GetInt64 gets int64 value. 128 func (d *Datum) GetInt64() int64 { 129 return d.i 130 } 131 132 // SetInt64 sets int64 value. 133 func (d *Datum) SetInt64(i int64) { 134 d.k = KindInt64 135 d.i = i 136 } 137 138 // GetUint64 gets uint64 value. 139 func (d *Datum) GetUint64() uint64 { 140 return uint64(d.i) 141 } 142 143 // SetUint64 sets uint64 value. 144 func (d *Datum) SetUint64(i uint64) { 145 d.k = KindUint64 146 d.i = int64(i) 147 } 148 149 // GetFloat64 gets float64 value. 150 func (d *Datum) GetFloat64() float64 { 151 return math.Float64frombits(uint64(d.i)) 152 } 153 154 // SetFloat64 sets float64 value. 155 func (d *Datum) SetFloat64(f float64) { 156 d.k = KindFloat64 157 d.i = int64(math.Float64bits(f)) 158 } 159 160 // GetFloat32 gets float32 value. 161 func (d *Datum) GetFloat32() float32 { 162 return float32(math.Float64frombits(uint64(d.i))) 163 } 164 165 // SetFloat32 sets float32 value. 166 func (d *Datum) SetFloat32(f float32) { 167 d.k = KindFloat32 168 d.i = int64(math.Float64bits(float64(f))) 169 } 170 171 // GetString gets string value. 172 func (d *Datum) GetString() string { 173 return string(hack.String(d.b)) 174 } 175 176 // SetString sets string value. 177 func (d *Datum) SetString(s string) { 178 d.k = KindString 179 sink(s) 180 d.b = hack.Slice(s) 181 } 182 183 // sink prevents s from being allocated on the stack. 184 var sink = func(s string) { 185 } 186 187 // GetBytes gets bytes value. 188 func (d *Datum) GetBytes() []byte { 189 return d.b 190 } 191 192 // SetBytes sets bytes value to datum. 193 func (d *Datum) SetBytes(b []byte) { 194 d.k = KindBytes 195 d.b = b 196 } 197 198 // SetBytesAsString sets bytes value to datum as string type. 199 func (d *Datum) SetBytesAsString(b []byte) { 200 d.k = KindString 201 d.b = b 202 } 203 204 // GetInterface gets interface value. 205 func (d *Datum) GetInterface() interface{} { 206 return d.x 207 } 208 209 // SetInterface sets interface to datum. 210 func (d *Datum) SetInterface(x interface{}) { 211 d.k = KindInterface 212 d.x = x 213 } 214 215 // SetNull sets datum to nil. 216 func (d *Datum) SetNull() { 217 d.k = KindNull 218 d.x = nil 219 } 220 221 // SetMinNotNull sets datum to minNotNull value. 222 func (d *Datum) SetMinNotNull() { 223 d.k = KindMinNotNull 224 d.x = nil 225 } 226 227 // GetBinaryLiteral gets Bit value 228 func (d *Datum) GetBinaryLiteral() BinaryLiteral { 229 return d.b 230 } 231 232 // GetMysqlBit gets MysqlBit value 233 func (d *Datum) GetMysqlBit() BinaryLiteral { 234 return d.GetBinaryLiteral() 235 } 236 237 // SetBinaryLiteral sets Bit value 238 func (d *Datum) SetBinaryLiteral(b BinaryLiteral) { 239 d.k = KindBinaryLiteral 240 d.b = b 241 } 242 243 // SetMysqlBit sets MysqlBit value 244 func (d *Datum) SetMysqlBit(b BinaryLiteral) { 245 d.k = KindMysqlBit 246 d.b = b 247 } 248 249 // GetMysqlDecimal gets Decimal value 250 func (d *Datum) GetMysqlDecimal() *MyDecimal { 251 return d.x.(*MyDecimal) 252 } 253 254 // SetMysqlDecimal sets Decimal value 255 func (d *Datum) SetMysqlDecimal(b *MyDecimal) { 256 d.k = KindMysqlDecimal 257 d.x = b 258 } 259 260 // GetMysqlDuration gets Duration value 261 func (d *Datum) GetMysqlDuration() Duration { 262 return Duration{Duration: time.Duration(d.i), Fsp: int(d.decimal)} 263 } 264 265 // SetMysqlDuration sets Duration value 266 func (d *Datum) SetMysqlDuration(b Duration) { 267 d.k = KindMysqlDuration 268 d.i = int64(b.Duration) 269 d.decimal = uint16(b.Fsp) 270 } 271 272 // GetMysqlEnum gets Enum value 273 func (d *Datum) GetMysqlEnum() Enum { 274 str := string(hack.String(d.b)) 275 return Enum{Value: uint64(d.i), Name: str} 276 } 277 278 // SetMysqlEnum sets Enum value 279 func (d *Datum) SetMysqlEnum(b Enum) { 280 d.k = KindMysqlEnum 281 d.i = int64(b.Value) 282 sink(b.Name) 283 d.b = hack.Slice(b.Name) 284 } 285 286 // GetMysqlSet gets Set value 287 func (d *Datum) GetMysqlSet() Set { 288 str := string(hack.String(d.b)) 289 return Set{Value: uint64(d.i), Name: str} 290 } 291 292 // SetMysqlSet sets Set value 293 func (d *Datum) SetMysqlSet(b Set) { 294 d.k = KindMysqlSet 295 d.i = int64(b.Value) 296 sink(b.Name) 297 d.b = hack.Slice(b.Name) 298 } 299 300 // GetMysqlJSON gets json.BinaryJSON value 301 func (d *Datum) GetMysqlJSON() json.BinaryJSON { 302 return json.BinaryJSON{TypeCode: byte(d.i), Value: d.b} 303 } 304 305 // SetMysqlJSON sets json.BinaryJSON value 306 func (d *Datum) SetMysqlJSON(b json.BinaryJSON) { 307 d.k = KindMysqlJSON 308 d.i = int64(b.TypeCode) 309 d.b = b.Value 310 } 311 312 // GetMysqlTime gets types.Time value 313 func (d *Datum) GetMysqlTime() Time { 314 return d.x.(Time) 315 } 316 317 // SetMysqlTime sets types.Time value 318 func (d *Datum) SetMysqlTime(b Time) { 319 d.k = KindMysqlTime 320 d.x = b 321 } 322 323 // SetRaw sets raw value. 324 func (d *Datum) SetRaw(b []byte) { 325 d.k = KindRaw 326 d.b = b 327 } 328 329 // GetRaw gets raw value. 330 func (d *Datum) GetRaw() []byte { 331 return d.b 332 } 333 334 // SetAutoID set the auto increment ID according to its int flag. 335 func (d *Datum) SetAutoID(id int64, flag uint) { 336 if mysql.HasUnsignedFlag(flag) { 337 d.SetUint64(uint64(id)) 338 } else { 339 d.SetInt64(id) 340 } 341 } 342 343 // GetValue gets the value of the datum of any kind. 344 func (d *Datum) GetValue() interface{} { 345 switch d.k { 346 case KindInt64: 347 return d.GetInt64() 348 case KindUint64: 349 return d.GetUint64() 350 case KindFloat32: 351 return d.GetFloat32() 352 case KindFloat64: 353 return d.GetFloat64() 354 case KindString: 355 return d.GetString() 356 case KindBytes: 357 return d.GetBytes() 358 case KindMysqlDecimal: 359 return d.GetMysqlDecimal() 360 case KindMysqlDuration: 361 return d.GetMysqlDuration() 362 case KindMysqlEnum: 363 return d.GetMysqlEnum() 364 case KindBinaryLiteral, KindMysqlBit: 365 return d.GetBinaryLiteral() 366 case KindMysqlSet: 367 return d.GetMysqlSet() 368 case KindMysqlJSON: 369 return d.GetMysqlJSON() 370 case KindMysqlTime: 371 return d.GetMysqlTime() 372 default: 373 return d.GetInterface() 374 } 375 } 376 377 // SetValue sets any kind of value. 378 func (d *Datum) SetValue(val interface{}) { 379 switch x := val.(type) { 380 case nil: 381 d.SetNull() 382 case bool: 383 if x { 384 d.SetInt64(1) 385 } else { 386 d.SetInt64(0) 387 } 388 case int: 389 d.SetInt64(int64(x)) 390 case int64: 391 d.SetInt64(x) 392 case uint64: 393 d.SetUint64(x) 394 case float32: 395 d.SetFloat32(x) 396 case float64: 397 d.SetFloat64(x) 398 case string: 399 d.SetString(x) 400 case []byte: 401 d.SetBytes(x) 402 case *MyDecimal: 403 d.SetMysqlDecimal(x) 404 case Duration: 405 d.SetMysqlDuration(x) 406 case Enum: 407 d.SetMysqlEnum(x) 408 case BinaryLiteral: 409 d.SetBinaryLiteral(x) 410 case BitLiteral: // Store as BinaryLiteral for Bit and Hex literals 411 d.SetBinaryLiteral(BinaryLiteral(x)) 412 case HexLiteral: 413 d.SetBinaryLiteral(BinaryLiteral(x)) 414 case Set: 415 d.SetMysqlSet(x) 416 case json.BinaryJSON: 417 d.SetMysqlJSON(x) 418 case Time: 419 d.SetMysqlTime(x) 420 default: 421 d.SetInterface(x) 422 } 423 } 424 425 // CompareDatum compares datum to another datum. 426 // TODO: return error properly. 427 func (d *Datum) CompareDatum(sc *stmtctx.StatementContext, ad *Datum) (int, error) { 428 if d.k == KindMysqlJSON && ad.k != KindMysqlJSON { 429 cmp, err := ad.CompareDatum(sc, d) 430 return cmp * -1, errors.Trace(err) 431 } 432 switch ad.k { 433 case KindNull: 434 if d.k == KindNull { 435 return 0, nil 436 } 437 return 1, nil 438 case KindMinNotNull: 439 if d.k == KindNull { 440 return -1, nil 441 } else if d.k == KindMinNotNull { 442 return 0, nil 443 } 444 return 1, nil 445 case KindMaxValue: 446 if d.k == KindMaxValue { 447 return 0, nil 448 } 449 return -1, nil 450 case KindInt64: 451 return d.compareInt64(sc, ad.GetInt64()) 452 case KindUint64: 453 return d.compareUint64(sc, ad.GetUint64()) 454 case KindFloat32, KindFloat64: 455 return d.compareFloat64(sc, ad.GetFloat64()) 456 case KindString: 457 return d.compareString(sc, ad.GetString()) 458 case KindBytes: 459 return d.compareBytes(sc, ad.GetBytes()) 460 case KindMysqlDecimal: 461 return d.compareMysqlDecimal(sc, ad.GetMysqlDecimal()) 462 case KindMysqlDuration: 463 return d.compareMysqlDuration(sc, ad.GetMysqlDuration()) 464 case KindMysqlEnum: 465 return d.compareMysqlEnum(sc, ad.GetMysqlEnum()) 466 case KindBinaryLiteral, KindMysqlBit: 467 return d.compareBinaryLiteral(sc, ad.GetBinaryLiteral()) 468 case KindMysqlSet: 469 return d.compareMysqlSet(sc, ad.GetMysqlSet()) 470 case KindMysqlJSON: 471 return d.compareMysqlJSON(sc, ad.GetMysqlJSON()) 472 case KindMysqlTime: 473 return d.compareMysqlTime(sc, ad.GetMysqlTime()) 474 default: 475 return 0, nil 476 } 477 } 478 479 func (d *Datum) compareInt64(sc *stmtctx.StatementContext, i int64) (int, error) { 480 switch d.k { 481 case KindMaxValue: 482 return 1, nil 483 case KindInt64: 484 return CompareInt64(d.i, i), nil 485 case KindUint64: 486 if i < 0 || d.GetUint64() > math.MaxInt64 { 487 return 1, nil 488 } 489 return CompareInt64(d.i, i), nil 490 default: 491 return d.compareFloat64(sc, float64(i)) 492 } 493 } 494 495 func (d *Datum) compareUint64(sc *stmtctx.StatementContext, u uint64) (int, error) { 496 switch d.k { 497 case KindMaxValue: 498 return 1, nil 499 case KindInt64: 500 if d.i < 0 || u > math.MaxInt64 { 501 return -1, nil 502 } 503 return CompareInt64(d.i, int64(u)), nil 504 case KindUint64: 505 return CompareUint64(d.GetUint64(), u), nil 506 default: 507 return d.compareFloat64(sc, float64(u)) 508 } 509 } 510 511 func (d *Datum) compareFloat64(sc *stmtctx.StatementContext, f float64) (int, error) { 512 switch d.k { 513 case KindNull, KindMinNotNull: 514 return -1, nil 515 case KindMaxValue: 516 return 1, nil 517 case KindInt64: 518 return CompareFloat64(float64(d.i), f), nil 519 case KindUint64: 520 return CompareFloat64(float64(d.GetUint64()), f), nil 521 case KindFloat32, KindFloat64: 522 return CompareFloat64(d.GetFloat64(), f), nil 523 case KindString, KindBytes: 524 fVal, err := StrToFloat(sc, d.GetString()) 525 return CompareFloat64(fVal, f), errors.Trace(err) 526 case KindMysqlDecimal: 527 fVal, err := d.GetMysqlDecimal().ToFloat64() 528 return CompareFloat64(fVal, f), errors.Trace(err) 529 case KindMysqlDuration: 530 fVal := d.GetMysqlDuration().Seconds() 531 return CompareFloat64(fVal, f), nil 532 case KindMysqlEnum: 533 fVal := d.GetMysqlEnum().ToNumber() 534 return CompareFloat64(fVal, f), nil 535 case KindBinaryLiteral, KindMysqlBit: 536 val, err := d.GetBinaryLiteral().ToInt(sc) 537 fVal := float64(val) 538 return CompareFloat64(fVal, f), errors.Trace(err) 539 case KindMysqlSet: 540 fVal := d.GetMysqlSet().ToNumber() 541 return CompareFloat64(fVal, f), nil 542 case KindMysqlTime: 543 fVal, err := d.GetMysqlTime().ToNumber().ToFloat64() 544 return CompareFloat64(fVal, f), errors.Trace(err) 545 default: 546 return -1, nil 547 } 548 } 549 550 func (d *Datum) compareString(sc *stmtctx.StatementContext, s string) (int, error) { 551 switch d.k { 552 case KindNull, KindMinNotNull: 553 return -1, nil 554 case KindMaxValue: 555 return 1, nil 556 case KindString, KindBytes: 557 return CompareString(d.GetString(), s), nil 558 case KindMysqlDecimal: 559 dec := new(MyDecimal) 560 err := sc.HandleTruncate(dec.FromString(hack.Slice(s))) 561 return d.GetMysqlDecimal().Compare(dec), errors.Trace(err) 562 case KindMysqlTime: 563 dt, err := ParseDatetime(sc, s) 564 return d.GetMysqlTime().Compare(dt), errors.Trace(err) 565 case KindMysqlDuration: 566 dur, err := ParseDuration(sc, s, MaxFsp) 567 return d.GetMysqlDuration().Compare(dur), errors.Trace(err) 568 case KindMysqlSet: 569 return CompareString(d.GetMysqlSet().String(), s), nil 570 case KindMysqlEnum: 571 return CompareString(d.GetMysqlEnum().String(), s), nil 572 case KindBinaryLiteral, KindMysqlBit: 573 return CompareString(d.GetBinaryLiteral().ToString(), s), nil 574 default: 575 fVal, err := StrToFloat(sc, s) 576 if err != nil { 577 return 0, errors.Trace(err) 578 } 579 return d.compareFloat64(sc, fVal) 580 } 581 } 582 583 func (d *Datum) compareBytes(sc *stmtctx.StatementContext, b []byte) (int, error) { 584 str := string(hack.String(b)) 585 return d.compareString(sc, str) 586 } 587 588 func (d *Datum) compareMysqlDecimal(sc *stmtctx.StatementContext, dec *MyDecimal) (int, error) { 589 switch d.k { 590 case KindNull, KindMinNotNull: 591 return -1, nil 592 case KindMaxValue: 593 return 1, nil 594 case KindMysqlDecimal: 595 return d.GetMysqlDecimal().Compare(dec), nil 596 case KindString, KindBytes: 597 dDec := new(MyDecimal) 598 err := sc.HandleTruncate(dDec.FromString(d.GetBytes())) 599 return dDec.Compare(dec), errors.Trace(err) 600 default: 601 dVal, err := d.ConvertTo(sc, NewFieldType(mysql.TypeNewDecimal)) 602 if err != nil { 603 return 0, errors.Trace(err) 604 } 605 return dVal.GetMysqlDecimal().Compare(dec), nil 606 } 607 } 608 609 func (d *Datum) compareMysqlDuration(sc *stmtctx.StatementContext, dur Duration) (int, error) { 610 switch d.k { 611 case KindMysqlDuration: 612 return d.GetMysqlDuration().Compare(dur), nil 613 case KindString, KindBytes: 614 dDur, err := ParseDuration(sc, d.GetString(), MaxFsp) 615 return dDur.Compare(dur), errors.Trace(err) 616 default: 617 return d.compareFloat64(sc, dur.Seconds()) 618 } 619 } 620 621 func (d *Datum) compareMysqlEnum(sc *stmtctx.StatementContext, enum Enum) (int, error) { 622 switch d.k { 623 case KindString, KindBytes: 624 return CompareString(d.GetString(), enum.String()), nil 625 default: 626 return d.compareFloat64(sc, enum.ToNumber()) 627 } 628 } 629 630 func (d *Datum) compareBinaryLiteral(sc *stmtctx.StatementContext, b BinaryLiteral) (int, error) { 631 switch d.k { 632 case KindString, KindBytes: 633 return CompareString(d.GetString(), b.ToString()), nil 634 case KindBinaryLiteral, KindMysqlBit: 635 return CompareString(d.GetBinaryLiteral().ToString(), b.ToString()), nil 636 default: 637 val, err := b.ToInt(sc) 638 if err != nil { 639 return 0, errors.Trace(err) 640 } 641 result, err := d.compareFloat64(sc, float64(val)) 642 return result, errors.Trace(err) 643 } 644 } 645 646 func (d *Datum) compareMysqlSet(sc *stmtctx.StatementContext, set Set) (int, error) { 647 switch d.k { 648 case KindString, KindBytes: 649 return CompareString(d.GetString(), set.String()), nil 650 default: 651 return d.compareFloat64(sc, set.ToNumber()) 652 } 653 } 654 655 func (d *Datum) compareMysqlJSON(sc *stmtctx.StatementContext, target json.BinaryJSON) (int, error) { 656 origin, err := d.ToMysqlJSON() 657 if err != nil { 658 return 0, errors.Trace(err) 659 } 660 return json.CompareBinary(origin, target), nil 661 } 662 663 func (d *Datum) compareMysqlTime(sc *stmtctx.StatementContext, time Time) (int, error) { 664 switch d.k { 665 case KindString, KindBytes: 666 dt, err := ParseDatetime(sc, d.GetString()) 667 return dt.Compare(time), errors.Trace(err) 668 case KindMysqlTime: 669 return d.GetMysqlTime().Compare(time), nil 670 default: 671 fVal, err := time.ToNumber().ToFloat64() 672 if err != nil { 673 return 0, errors.Trace(err) 674 } 675 return d.compareFloat64(sc, fVal) 676 } 677 } 678 679 // ConvertTo converts a datum to the target field type. 680 func (d *Datum) ConvertTo(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 681 if d.k == KindNull { 682 return Datum{}, nil 683 } 684 switch target.Tp { // TODO: implement mysql types convert when "CAST() AS" syntax are supported. 685 case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong: 686 unsigned := mysql.HasUnsignedFlag(target.Flag) 687 if unsigned { 688 return d.convertToUint(sc, target) 689 } 690 return d.convertToInt(sc, target) 691 case mysql.TypeFloat, mysql.TypeDouble: 692 return d.convertToFloat(sc, target) 693 case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, 694 mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString: 695 return d.convertToString(sc, target) 696 case mysql.TypeTimestamp: 697 return d.convertToMysqlTimestamp(sc, target) 698 case mysql.TypeDatetime, mysql.TypeDate: 699 return d.convertToMysqlTime(sc, target) 700 case mysql.TypeDuration: 701 return d.convertToMysqlDuration(sc, target) 702 case mysql.TypeNewDecimal: 703 return d.convertToMysqlDecimal(sc, target) 704 case mysql.TypeYear: 705 return d.convertToMysqlYear(sc, target) 706 case mysql.TypeEnum: 707 return d.convertToMysqlEnum(sc, target) 708 case mysql.TypeBit: 709 return d.convertToMysqlBit(sc, target) 710 case mysql.TypeSet: 711 return d.convertToMysqlSet(sc, target) 712 case mysql.TypeJSON: 713 return d.convertToMysqlJSON(sc, target) 714 case mysql.TypeNull: 715 return Datum{}, nil 716 default: 717 panic("should never happen") 718 } 719 } 720 721 func (d *Datum) convertToFloat(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 722 var ( 723 f float64 724 ret Datum 725 err error 726 ) 727 switch d.k { 728 case KindNull: 729 return ret, nil 730 case KindInt64: 731 f = float64(d.GetInt64()) 732 case KindUint64: 733 f = float64(d.GetUint64()) 734 case KindFloat32, KindFloat64: 735 f = d.GetFloat64() 736 case KindString, KindBytes: 737 f, err = StrToFloat(sc, d.GetString()) 738 case KindMysqlTime: 739 f, err = d.GetMysqlTime().ToNumber().ToFloat64() 740 case KindMysqlDuration: 741 f, err = d.GetMysqlDuration().ToNumber().ToFloat64() 742 case KindMysqlDecimal: 743 f, err = d.GetMysqlDecimal().ToFloat64() 744 case KindMysqlSet: 745 f = d.GetMysqlSet().ToNumber() 746 case KindMysqlEnum: 747 f = d.GetMysqlEnum().ToNumber() 748 case KindBinaryLiteral, KindMysqlBit: 749 val, err1 := d.GetBinaryLiteral().ToInt(sc) 750 f, err = float64(val), err1 751 case KindMysqlJSON: 752 f, err = ConvertJSONToFloat(sc, d.GetMysqlJSON()) 753 default: 754 return invalidConv(d, target.Tp) 755 } 756 var err1 error 757 f, err1 = ProduceFloatWithSpecifiedTp(f, target, sc) 758 if err == nil && err1 != nil { 759 err = err1 760 } 761 if target.Tp == mysql.TypeFloat { 762 ret.SetFloat32(float32(f)) 763 } else { 764 ret.SetFloat64(f) 765 } 766 return ret, errors.Trace(err) 767 } 768 769 // ProduceFloatWithSpecifiedTp produces a new float64 according to `flen` and `decimal`. 770 func ProduceFloatWithSpecifiedTp(f float64, target *FieldType, sc *stmtctx.StatementContext) (_ float64, err error) { 771 // For float and following double type, we will only truncate it for float(M, D) format. 772 // If no D is set, we will handle it like origin float whether M is set or not. 773 if target.Flen != UnspecifiedLength && target.Decimal != UnspecifiedLength { 774 f, err = TruncateFloat(f, target.Flen, target.Decimal) 775 if err = sc.HandleOverflow(err, err); err != nil { 776 return f, errors.Trace(err) 777 } 778 } 779 if mysql.HasUnsignedFlag(target.Flag) && f < 0 { 780 return 0, overflow(f, target.Tp) 781 } 782 return f, nil 783 } 784 785 func (d *Datum) convertToString(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 786 var ret Datum 787 var s string 788 switch d.k { 789 case KindInt64: 790 s = strconv.FormatInt(d.GetInt64(), 10) 791 case KindUint64: 792 s = strconv.FormatUint(d.GetUint64(), 10) 793 case KindFloat32: 794 s = strconv.FormatFloat(d.GetFloat64(), 'f', -1, 32) 795 case KindFloat64: 796 s = strconv.FormatFloat(d.GetFloat64(), 'f', -1, 64) 797 case KindString, KindBytes: 798 s = d.GetString() 799 case KindMysqlTime: 800 s = d.GetMysqlTime().String() 801 case KindMysqlDuration: 802 s = d.GetMysqlDuration().String() 803 case KindMysqlDecimal: 804 s = d.GetMysqlDecimal().String() 805 case KindMysqlEnum: 806 s = d.GetMysqlEnum().String() 807 case KindMysqlSet: 808 s = d.GetMysqlSet().String() 809 case KindBinaryLiteral, KindMysqlBit: 810 s = d.GetBinaryLiteral().ToString() 811 case KindMysqlJSON: 812 s = d.GetMysqlJSON().String() 813 default: 814 return invalidConv(d, target.Tp) 815 } 816 s, err := ProduceStrWithSpecifiedTp(s, target, sc, true) 817 ret.SetString(s) 818 if target.Charset == mysql.CharsetBin { 819 ret.k = KindBytes 820 } 821 return ret, errors.Trace(err) 822 } 823 824 // ProduceStrWithSpecifiedTp produces a new string according to `flen` and `chs`. Param `padZero` indicates 825 // whether we should pad `\0` for `binary(flen)` type. 826 func ProduceStrWithSpecifiedTp(s string, tp *FieldType, sc *stmtctx.StatementContext, padZero bool) (_ string, err error) { 827 flen, chs := tp.Flen, tp.Charset 828 if flen >= 0 { 829 // Flen is the rune length, not binary length, for UTF8 charset, we need to calculate the 830 // rune count and truncate to Flen runes if it is too long. 831 if chs == mysql.CharsetUTF8 || chs == mysql.CharsetUTF8MB4 { 832 characterLen := utf8.RuneCountInString(s) 833 if characterLen > flen { 834 // 1. If len(s) is 0 and flen is 0, truncateLen will be 0, don't truncate s. 835 // CREATE TABLE t (a char(0)); 836 // INSERT INTO t VALUES (``); 837 // 2. If len(s) is 10 and flen is 0, truncateLen will be 0 too, but we still need to truncate s. 838 // SELECT 1, CAST(1234 AS CHAR(0)); 839 // So truncateLen is not a suitable variable to determine to do truncate or not. 840 var runeCount int 841 var truncateLen int 842 for i := range s { 843 if runeCount == flen { 844 truncateLen = i 845 break 846 } 847 runeCount++ 848 } 849 err = ErrDataTooLong.GenWithStack("Data Too Long, field len %d, data len %d", flen, characterLen) 850 s = truncateStr(s, truncateLen) 851 } 852 } else if len(s) > flen { 853 err = ErrDataTooLong.GenWithStack("Data Too Long, field len %d, data len %d", flen, len(s)) 854 s = truncateStr(s, flen) 855 } else if tp.Tp == mysql.TypeString && IsBinaryStr(tp) && len(s) < flen && padZero { 856 padding := make([]byte, flen-len(s)) 857 s = string(append([]byte(s), padding...)) 858 } 859 } 860 return s, errors.Trace(sc.HandleTruncate(err)) 861 } 862 863 func (d *Datum) convertToInt(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 864 i64, err := d.toSignedInteger(sc, target.Tp) 865 return NewIntDatum(i64), errors.Trace(err) 866 } 867 868 func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 869 tp := target.Tp 870 upperBound := UnsignedUpperBound[tp] 871 var ( 872 val uint64 873 err error 874 ret Datum 875 ) 876 switch d.k { 877 case KindInt64: 878 val, err = ConvertIntToUint(sc, d.GetInt64(), upperBound, tp) 879 case KindUint64: 880 val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp) 881 case KindFloat32, KindFloat64: 882 val, err = ConvertFloatToUint(sc, d.GetFloat64(), upperBound, tp) 883 case KindString, KindBytes: 884 uval, err1 := StrToUint(sc, d.GetString()) 885 if err1 != nil && ErrOverflow.Equal(err1) && !sc.ShouldIgnoreOverflowError() { 886 return ret, errors.Trace(err1) 887 } 888 val, err = ConvertUintToUint(uval, upperBound, tp) 889 if err != nil { 890 return ret, errors.Trace(err) 891 } 892 err = err1 893 case KindMysqlTime: 894 dec := d.GetMysqlTime().ToNumber() 895 err = dec.Round(dec, 0, ModeHalfEven) 896 ival, err1 := dec.ToInt() 897 if err == nil { 898 err = err1 899 } 900 val, err1 = ConvertIntToUint(sc, ival, upperBound, tp) 901 if err == nil { 902 err = err1 903 } 904 case KindMysqlDuration: 905 dec := d.GetMysqlDuration().ToNumber() 906 err = dec.Round(dec, 0, ModeHalfEven) 907 ival, err1 := dec.ToInt() 908 if err1 == nil { 909 val, err = ConvertIntToUint(sc, ival, upperBound, tp) 910 } 911 case KindMysqlDecimal: 912 fval, err1 := d.GetMysqlDecimal().ToFloat64() 913 val, err = ConvertFloatToUint(sc, fval, upperBound, tp) 914 if err == nil { 915 err = err1 916 } 917 case KindMysqlEnum: 918 val, err = ConvertFloatToUint(sc, d.GetMysqlEnum().ToNumber(), upperBound, tp) 919 case KindMysqlSet: 920 val, err = ConvertFloatToUint(sc, d.GetMysqlSet().ToNumber(), upperBound, tp) 921 case KindBinaryLiteral, KindMysqlBit: 922 val, err = d.GetBinaryLiteral().ToInt(sc) 923 case KindMysqlJSON: 924 var i64 int64 925 i64, err = ConvertJSONToInt(sc, d.GetMysqlJSON(), true) 926 val = uint64(i64) 927 default: 928 return invalidConv(d, target.Tp) 929 } 930 ret.SetUint64(val) 931 if err != nil { 932 return ret, errors.Trace(err) 933 } 934 return ret, nil 935 } 936 937 func (d *Datum) convertToMysqlTimestamp(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 938 var ( 939 ret Datum 940 t Time 941 err error 942 ) 943 fsp := DefaultFsp 944 if target.Decimal != UnspecifiedLength { 945 fsp = target.Decimal 946 } 947 switch d.k { 948 case KindMysqlTime: 949 t = d.GetMysqlTime() 950 t, err = t.RoundFrac(sc, fsp) 951 case KindMysqlDuration: 952 t, err = d.GetMysqlDuration().ConvertToTime(sc, mysql.TypeTimestamp) 953 if err != nil { 954 ret.SetValue(t) 955 return ret, errors.Trace(err) 956 } 957 t, err = t.RoundFrac(sc, fsp) 958 case KindString, KindBytes: 959 t, err = ParseTime(sc, d.GetString(), mysql.TypeTimestamp, fsp) 960 case KindInt64: 961 t, err = ParseTimeFromNum(sc, d.GetInt64(), mysql.TypeTimestamp, fsp) 962 default: 963 return invalidConv(d, mysql.TypeTimestamp) 964 } 965 t.Type = mysql.TypeTimestamp 966 ret.SetMysqlTime(t) 967 if err != nil { 968 return ret, errors.Trace(err) 969 } 970 return ret, nil 971 } 972 973 func (d *Datum) convertToMysqlTime(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 974 tp := target.Tp 975 fsp := DefaultFsp 976 if target.Decimal != UnspecifiedLength { 977 fsp = target.Decimal 978 } 979 var ( 980 ret Datum 981 t Time 982 err error 983 ) 984 switch d.k { 985 case KindMysqlTime: 986 t, err = d.GetMysqlTime().Convert(sc, tp) 987 if err != nil { 988 ret.SetValue(t) 989 return ret, errors.Trace(err) 990 } 991 t, err = t.RoundFrac(sc, fsp) 992 case KindMysqlDuration: 993 t, err = d.GetMysqlDuration().ConvertToTime(sc, tp) 994 if err != nil { 995 ret.SetValue(t) 996 return ret, errors.Trace(err) 997 } 998 t, err = t.RoundFrac(sc, fsp) 999 case KindString, KindBytes: 1000 t, err = ParseTime(sc, d.GetString(), tp, fsp) 1001 case KindInt64: 1002 t, err = ParseTimeFromNum(sc, d.GetInt64(), tp, fsp) 1003 default: 1004 return invalidConv(d, tp) 1005 } 1006 if tp == mysql.TypeDate { 1007 // Truncate hh:mm:ss part if the type is Date. 1008 t.Time = FromDate(t.Time.Year(), t.Time.Month(), t.Time.Day(), 0, 0, 0, 0) 1009 } 1010 ret.SetValue(t) 1011 if err != nil { 1012 return ret, errors.Trace(err) 1013 } 1014 return ret, nil 1015 } 1016 1017 func (d *Datum) convertToMysqlDuration(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1018 tp := target.Tp 1019 fsp := DefaultFsp 1020 if target.Decimal != UnspecifiedLength { 1021 fsp = target.Decimal 1022 } 1023 var ret Datum 1024 switch d.k { 1025 case KindMysqlTime: 1026 dur, err := d.GetMysqlTime().ConvertToDuration() 1027 if err != nil { 1028 ret.SetValue(dur) 1029 return ret, errors.Trace(err) 1030 } 1031 dur, err = dur.RoundFrac(fsp) 1032 ret.SetValue(dur) 1033 if err != nil { 1034 return ret, errors.Trace(err) 1035 } 1036 case KindMysqlDuration: 1037 dur, err := d.GetMysqlDuration().RoundFrac(fsp) 1038 ret.SetValue(dur) 1039 if err != nil { 1040 return ret, errors.Trace(err) 1041 } 1042 case KindInt64, KindFloat32, KindFloat64, KindMysqlDecimal: 1043 // TODO: We need a ParseDurationFromNum to avoid the cost of converting a num to string. 1044 timeStr, err := d.ToString() 1045 if err != nil { 1046 return ret, errors.Trace(err) 1047 } 1048 timeNum, err := d.ToInt64(sc) 1049 if err != nil { 1050 return ret, errors.Trace(err) 1051 } 1052 // For huge numbers(>'0001-00-00 00-00-00') try full DATETIME in ParseDuration. 1053 if timeNum > MaxDuration && timeNum < 10000000000 { 1054 // mysql return max in no strict sql mode. 1055 ret.SetValue(Duration{Duration: MaxTime, Fsp: 0}) 1056 return ret, ErrInvalidTimeFormat.GenWithStack("Incorrect time value: '%s'", timeStr) 1057 } 1058 if timeNum < -MaxDuration { 1059 return ret, ErrInvalidTimeFormat.GenWithStack("Incorrect time value: '%s'", timeStr) 1060 } 1061 t, err := ParseDuration(sc, timeStr, fsp) 1062 ret.SetValue(t) 1063 if err != nil { 1064 return ret, errors.Trace(err) 1065 } 1066 case KindString, KindBytes: 1067 t, err := ParseDuration(sc, d.GetString(), fsp) 1068 ret.SetValue(t) 1069 if err != nil { 1070 return ret, errors.Trace(err) 1071 } 1072 default: 1073 return invalidConv(d, tp) 1074 } 1075 return ret, nil 1076 } 1077 1078 func (d *Datum) convertToMysqlDecimal(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1079 var ret Datum 1080 ret.SetLength(target.Flen) 1081 ret.SetFrac(target.Decimal) 1082 var dec = &MyDecimal{} 1083 var err error 1084 switch d.k { 1085 case KindInt64: 1086 dec.FromInt(d.GetInt64()) 1087 case KindUint64: 1088 dec.FromUint(d.GetUint64()) 1089 case KindFloat32, KindFloat64: 1090 err = dec.FromFloat64(d.GetFloat64()) 1091 case KindString, KindBytes: 1092 err = dec.FromString(d.GetBytes()) 1093 case KindMysqlDecimal: 1094 *dec = *d.GetMysqlDecimal() 1095 case KindMysqlTime: 1096 dec = d.GetMysqlTime().ToNumber() 1097 case KindMysqlDuration: 1098 dec = d.GetMysqlDuration().ToNumber() 1099 case KindMysqlEnum: 1100 err = dec.FromFloat64(d.GetMysqlEnum().ToNumber()) 1101 case KindMysqlSet: 1102 err = dec.FromFloat64(d.GetMysqlSet().ToNumber()) 1103 case KindBinaryLiteral, KindMysqlBit: 1104 val, err1 := d.GetBinaryLiteral().ToInt(sc) 1105 err = err1 1106 dec.FromUint(val) 1107 case KindMysqlJSON: 1108 f, err1 := ConvertJSONToFloat(sc, d.GetMysqlJSON()) 1109 if err1 != nil { 1110 return ret, errors.Trace(err1) 1111 } 1112 err = dec.FromFloat64(f) 1113 default: 1114 return invalidConv(d, target.Tp) 1115 } 1116 var err1 error 1117 dec, err1 = ProduceDecWithSpecifiedTp(dec, target, sc) 1118 if err == nil && err1 != nil { 1119 err = err1 1120 } 1121 if dec.negative && mysql.HasUnsignedFlag(target.Flag) { 1122 *dec = zeroMyDecimal 1123 if err == nil { 1124 err = ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%d, %d)", target.Flen, target.Decimal)) 1125 } 1126 } 1127 ret.SetValue(dec) 1128 return ret, errors.Trace(err) 1129 } 1130 1131 // ProduceDecWithSpecifiedTp produces a new decimal according to `flen` and `decimal`. 1132 func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.StatementContext) (_ *MyDecimal, err error) { 1133 flen, decimal := tp.Flen, tp.Decimal 1134 if flen != UnspecifiedLength && decimal != UnspecifiedLength { 1135 if flen < decimal { 1136 return nil, ErrMBiggerThanD.GenWithStackByArgs("") 1137 } 1138 prec, frac := dec.PrecisionAndFrac() 1139 if !dec.IsZero() && prec-frac > flen-decimal { 1140 dec = NewMaxOrMinDec(dec.IsNegative(), flen, decimal) 1141 // select (cast 111 as decimal(1)) causes a warning in MySQL. 1142 err = ErrOverflow.GenWithStackByArgs("DECIMAL", fmt.Sprintf("(%d, %d)", flen, decimal)) 1143 } else if frac != decimal { 1144 old := *dec 1145 err = dec.Round(dec, decimal, ModeHalfEven) 1146 if err != nil { 1147 return nil, errors.Trace(err) 1148 } 1149 if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 { 1150 if sc.InInsertStmt || sc.InUpdateStmt || sc.InDeleteStmt { 1151 // fix https://github.com/pingcap/tidb/issues/3895 1152 // fix https://github.com/pingcap/tidb/issues/5532 1153 sc.AppendWarning(ErrTruncated) 1154 err = nil 1155 } else { 1156 err = sc.HandleTruncate(ErrTruncated) 1157 } 1158 } 1159 } 1160 } 1161 1162 if ErrOverflow.Equal(err) { 1163 // TODO: warnErr need to be ErrWarnDataOutOfRange 1164 err = sc.HandleOverflow(err, err) 1165 } 1166 unsigned := mysql.HasUnsignedFlag(tp.Flag) 1167 if unsigned && dec.IsNegative() { 1168 dec = dec.FromUint(0) 1169 } 1170 return dec, errors.Trace(err) 1171 } 1172 1173 func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1174 var ( 1175 ret Datum 1176 y int64 1177 err error 1178 adjust bool 1179 ) 1180 switch d.k { 1181 case KindString, KindBytes: 1182 s := d.GetString() 1183 y, err = StrToInt(sc, s) 1184 if err != nil { 1185 return ret, errors.Trace(err) 1186 } 1187 adjust = len(s) < 4 1188 case KindMysqlTime: 1189 y = int64(d.GetMysqlTime().Time.Year()) 1190 case KindMysqlDuration: 1191 y = int64(time.Now().Year()) 1192 default: 1193 ret, err = d.convertToInt(sc, NewFieldType(mysql.TypeLonglong)) 1194 if err != nil { 1195 return invalidConv(d, target.Tp) 1196 } 1197 y = ret.GetInt64() 1198 } 1199 y, err = AdjustYear(y, adjust) 1200 if err != nil { 1201 return invalidConv(d, target.Tp) 1202 } 1203 ret.SetInt64(y) 1204 return ret, nil 1205 } 1206 1207 func (d *Datum) convertToMysqlBit(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1208 var ret Datum 1209 var uintValue uint64 1210 var err error 1211 switch d.k { 1212 case KindString, KindBytes: 1213 uintValue, err = BinaryLiteral(d.b).ToInt(sc) 1214 default: 1215 uintDatum, err1 := d.convertToUint(sc, target) 1216 uintValue, err = uintDatum.GetUint64(), err1 1217 } 1218 if target.Flen < 64 && uintValue >= 1<<(uint64(target.Flen)) { 1219 return Datum{}, errors.Trace(ErrOverflow.GenWithStackByArgs("BIT", fmt.Sprintf("(%d)", target.Flen))) 1220 } 1221 byteSize := (target.Flen + 7) >> 3 1222 ret.SetMysqlBit(NewBinaryLiteralFromUint(uintValue, byteSize)) 1223 return ret, errors.Trace(err) 1224 } 1225 1226 func (d *Datum) convertToMysqlEnum(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1227 var ( 1228 ret Datum 1229 e Enum 1230 err error 1231 ) 1232 switch d.k { 1233 case KindString, KindBytes: 1234 e, err = ParseEnumName(target.Elems, d.GetString()) 1235 default: 1236 var uintDatum Datum 1237 uintDatum, err = d.convertToUint(sc, target) 1238 if err != nil { 1239 return ret, errors.Trace(err) 1240 } 1241 e, err = ParseEnumValue(target.Elems, uintDatum.GetUint64()) 1242 } 1243 if err != nil { 1244 log.Warn(err.Error()) 1245 err = errors.Trace(ErrTruncated) 1246 } 1247 ret.SetValue(e) 1248 return ret, err 1249 } 1250 1251 func (d *Datum) convertToMysqlSet(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { 1252 var ( 1253 ret Datum 1254 s Set 1255 err error 1256 ) 1257 switch d.k { 1258 case KindString, KindBytes: 1259 s, err = ParseSetName(target.Elems, d.GetString()) 1260 default: 1261 var uintDatum Datum 1262 uintDatum, err = d.convertToUint(sc, target) 1263 if err != nil { 1264 return ret, errors.Trace(err) 1265 } 1266 s, err = ParseSetValue(target.Elems, uintDatum.GetUint64()) 1267 } 1268 1269 if err != nil { 1270 return invalidConv(d, target.Tp) 1271 } 1272 ret.SetValue(s) 1273 return ret, nil 1274 } 1275 1276 func (d *Datum) convertToMysqlJSON(sc *stmtctx.StatementContext, target *FieldType) (ret Datum, err error) { 1277 switch d.k { 1278 case KindString, KindBytes: 1279 var j json.BinaryJSON 1280 if j, err = json.ParseBinaryFromString(d.GetString()); err == nil { 1281 ret.SetMysqlJSON(j) 1282 } 1283 case KindInt64: 1284 i64 := d.GetInt64() 1285 ret.SetMysqlJSON(json.CreateBinary(i64)) 1286 case KindUint64: 1287 u64 := d.GetUint64() 1288 ret.SetMysqlJSON(json.CreateBinary(u64)) 1289 case KindFloat32, KindFloat64: 1290 f64 := d.GetFloat64() 1291 ret.SetMysqlJSON(json.CreateBinary(f64)) 1292 case KindMysqlDecimal: 1293 var f64 float64 1294 if f64, err = d.GetMysqlDecimal().ToFloat64(); err == nil { 1295 ret.SetMysqlJSON(json.CreateBinary(f64)) 1296 } 1297 case KindMysqlJSON: 1298 ret = *d 1299 default: 1300 var s string 1301 if s, err = d.ToString(); err == nil { 1302 // TODO: fix precision of MysqlTime. For example, 1303 // On MySQL 5.7 CAST(NOW() AS JSON) -> "2011-11-11 11:11:11.111111", 1304 // But now we can only return "2011-11-11 11:11:11". 1305 ret.SetMysqlJSON(json.CreateBinary(s)) 1306 } 1307 } 1308 return ret, errors.Trace(err) 1309 } 1310 1311 // ToBool converts to a bool. 1312 // We will use 1 for true, and 0 for false. 1313 func (d *Datum) ToBool(sc *stmtctx.StatementContext) (int64, error) { 1314 var err error 1315 isZero := false 1316 switch d.Kind() { 1317 case KindInt64: 1318 isZero = d.GetInt64() == 0 1319 case KindUint64: 1320 isZero = d.GetUint64() == 0 1321 case KindFloat32: 1322 isZero = RoundFloat(d.GetFloat64()) == 0 1323 case KindFloat64: 1324 isZero = RoundFloat(d.GetFloat64()) == 0 1325 case KindString, KindBytes: 1326 iVal, err1 := StrToInt(sc, d.GetString()) 1327 isZero, err = iVal == 0, err1 1328 case KindMysqlTime: 1329 isZero = d.GetMysqlTime().IsZero() 1330 case KindMysqlDuration: 1331 isZero = d.GetMysqlDuration().Duration == 0 1332 case KindMysqlDecimal: 1333 v, err1 := d.GetMysqlDecimal().ToFloat64() 1334 isZero, err = RoundFloat(v) == 0, err1 1335 case KindMysqlEnum: 1336 isZero = d.GetMysqlEnum().ToNumber() == 0 1337 case KindMysqlSet: 1338 isZero = d.GetMysqlSet().ToNumber() == 0 1339 case KindBinaryLiteral, KindMysqlBit: 1340 val, err1 := d.GetBinaryLiteral().ToInt(sc) 1341 isZero, err = val == 0, err1 1342 default: 1343 return 0, errors.Errorf("cannot convert %v(type %T) to bool", d.GetValue(), d.GetValue()) 1344 } 1345 var ret int64 1346 if isZero { 1347 ret = 0 1348 } else { 1349 ret = 1 1350 } 1351 if err != nil { 1352 return ret, errors.Trace(err) 1353 } 1354 return ret, nil 1355 } 1356 1357 // ConvertDatumToDecimal converts datum to decimal. 1358 func ConvertDatumToDecimal(sc *stmtctx.StatementContext, d Datum) (*MyDecimal, error) { 1359 dec := new(MyDecimal) 1360 var err error 1361 switch d.Kind() { 1362 case KindInt64: 1363 dec.FromInt(d.GetInt64()) 1364 case KindUint64: 1365 dec.FromUint(d.GetUint64()) 1366 case KindFloat32: 1367 err = dec.FromFloat64(float64(d.GetFloat32())) 1368 case KindFloat64: 1369 err = dec.FromFloat64(d.GetFloat64()) 1370 case KindString: 1371 err = sc.HandleTruncate(dec.FromString(d.GetBytes())) 1372 case KindMysqlDecimal: 1373 *dec = *d.GetMysqlDecimal() 1374 case KindMysqlEnum: 1375 dec.FromUint(d.GetMysqlEnum().Value) 1376 case KindMysqlSet: 1377 dec.FromUint(d.GetMysqlSet().Value) 1378 case KindBinaryLiteral, KindMysqlBit: 1379 val, err1 := d.GetBinaryLiteral().ToInt(sc) 1380 dec.FromUint(val) 1381 err = err1 1382 case KindMysqlJSON: 1383 f, err1 := ConvertJSONToFloat(sc, d.GetMysqlJSON()) 1384 if err1 != nil { 1385 return nil, errors.Trace(err1) 1386 } 1387 err = dec.FromFloat64(f) 1388 default: 1389 err = fmt.Errorf("can't convert %v to decimal", d.GetValue()) 1390 } 1391 return dec, errors.Trace(err) 1392 } 1393 1394 // ToDecimal converts to a decimal. 1395 func (d *Datum) ToDecimal(sc *stmtctx.StatementContext) (*MyDecimal, error) { 1396 switch d.Kind() { 1397 case KindMysqlTime: 1398 return d.GetMysqlTime().ToNumber(), nil 1399 case KindMysqlDuration: 1400 return d.GetMysqlDuration().ToNumber(), nil 1401 default: 1402 return ConvertDatumToDecimal(sc, *d) 1403 } 1404 } 1405 1406 // ToInt64 converts to a int64. 1407 func (d *Datum) ToInt64(sc *stmtctx.StatementContext) (int64, error) { 1408 return d.toSignedInteger(sc, mysql.TypeLonglong) 1409 } 1410 1411 func (d *Datum) toSignedInteger(sc *stmtctx.StatementContext, tp byte) (int64, error) { 1412 lowerBound := SignedLowerBound[tp] 1413 upperBound := SignedUpperBound[tp] 1414 switch d.Kind() { 1415 case KindInt64: 1416 return ConvertIntToInt(d.GetInt64(), lowerBound, upperBound, tp) 1417 case KindUint64: 1418 return ConvertUintToInt(d.GetUint64(), upperBound, tp) 1419 case KindFloat32: 1420 return ConvertFloatToInt(float64(d.GetFloat32()), lowerBound, upperBound, tp) 1421 case KindFloat64: 1422 return ConvertFloatToInt(d.GetFloat64(), lowerBound, upperBound, tp) 1423 case KindString, KindBytes: 1424 iVal, err := StrToInt(sc, d.GetString()) 1425 iVal, err2 := ConvertIntToInt(iVal, lowerBound, upperBound, tp) 1426 if err == nil { 1427 err = err2 1428 } 1429 return iVal, errors.Trace(err) 1430 case KindMysqlTime: 1431 // 2011-11-10 11:11:11.999999 -> 20111110111112 1432 // 2011-11-10 11:59:59.999999 -> 20111110120000 1433 t, err := d.GetMysqlTime().RoundFrac(sc, DefaultFsp) 1434 if err != nil { 1435 return 0, errors.Trace(err) 1436 } 1437 ival, err := t.ToNumber().ToInt() 1438 ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) 1439 if err == nil { 1440 err = err2 1441 } 1442 return ival, errors.Trace(err) 1443 case KindMysqlDuration: 1444 // 11:11:11.999999 -> 111112 1445 // 11:59:59.999999 -> 120000 1446 dur, err := d.GetMysqlDuration().RoundFrac(DefaultFsp) 1447 if err != nil { 1448 return 0, errors.Trace(err) 1449 } 1450 ival, err := dur.ToNumber().ToInt() 1451 ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) 1452 if err == nil { 1453 err = err2 1454 } 1455 return ival, errors.Trace(err) 1456 case KindMysqlDecimal: 1457 var to MyDecimal 1458 err := d.GetMysqlDecimal().Round(&to, 0, ModeHalfEven) 1459 ival, err1 := to.ToInt() 1460 if err == nil { 1461 err = err1 1462 } 1463 ival, err2 := ConvertIntToInt(ival, lowerBound, upperBound, tp) 1464 if err == nil { 1465 err = err2 1466 } 1467 return ival, errors.Trace(err) 1468 case KindMysqlEnum: 1469 fval := d.GetMysqlEnum().ToNumber() 1470 return ConvertFloatToInt(fval, lowerBound, upperBound, tp) 1471 case KindMysqlSet: 1472 fval := d.GetMysqlSet().ToNumber() 1473 return ConvertFloatToInt(fval, lowerBound, upperBound, tp) 1474 case KindMysqlJSON: 1475 return ConvertJSONToInt(sc, d.GetMysqlJSON(), false) 1476 case KindBinaryLiteral, KindMysqlBit: 1477 val, err := d.GetBinaryLiteral().ToInt(sc) 1478 return int64(val), errors.Trace(err) 1479 default: 1480 return 0, errors.Errorf("cannot convert %v(type %T) to int64", d.GetValue(), d.GetValue()) 1481 } 1482 } 1483 1484 // ToFloat64 converts to a float64 1485 func (d *Datum) ToFloat64(sc *stmtctx.StatementContext) (float64, error) { 1486 switch d.Kind() { 1487 case KindInt64: 1488 return float64(d.GetInt64()), nil 1489 case KindUint64: 1490 return float64(d.GetUint64()), nil 1491 case KindFloat32: 1492 return float64(d.GetFloat32()), nil 1493 case KindFloat64: 1494 return d.GetFloat64(), nil 1495 case KindString: 1496 return StrToFloat(sc, d.GetString()) 1497 case KindBytes: 1498 return StrToFloat(sc, string(d.GetBytes())) 1499 case KindMysqlTime: 1500 f, err := d.GetMysqlTime().ToNumber().ToFloat64() 1501 return f, errors.Trace(err) 1502 case KindMysqlDuration: 1503 f, err := d.GetMysqlDuration().ToNumber().ToFloat64() 1504 return f, errors.Trace(err) 1505 case KindMysqlDecimal: 1506 f, err := d.GetMysqlDecimal().ToFloat64() 1507 return f, errors.Trace(err) 1508 case KindMysqlEnum: 1509 return d.GetMysqlEnum().ToNumber(), nil 1510 case KindMysqlSet: 1511 return d.GetMysqlSet().ToNumber(), nil 1512 case KindBinaryLiteral, KindMysqlBit: 1513 val, err := d.GetBinaryLiteral().ToInt(sc) 1514 return float64(val), errors.Trace(err) 1515 case KindMysqlJSON: 1516 f, err := ConvertJSONToFloat(sc, d.GetMysqlJSON()) 1517 return f, errors.Trace(err) 1518 default: 1519 return 0, errors.Errorf("cannot convert %v(type %T) to float64", d.GetValue(), d.GetValue()) 1520 } 1521 } 1522 1523 // ToString gets the string representation of the datum. 1524 func (d *Datum) ToString() (string, error) { 1525 switch d.Kind() { 1526 case KindInt64: 1527 return strconv.FormatInt(d.GetInt64(), 10), nil 1528 case KindUint64: 1529 return strconv.FormatUint(d.GetUint64(), 10), nil 1530 case KindFloat32: 1531 return strconv.FormatFloat(float64(d.GetFloat32()), 'f', -1, 32), nil 1532 case KindFloat64: 1533 return strconv.FormatFloat(d.GetFloat64(), 'f', -1, 64), nil 1534 case KindString: 1535 return d.GetString(), nil 1536 case KindBytes: 1537 return d.GetString(), nil 1538 case KindMysqlTime: 1539 return d.GetMysqlTime().String(), nil 1540 case KindMysqlDuration: 1541 return d.GetMysqlDuration().String(), nil 1542 case KindMysqlDecimal: 1543 return d.GetMysqlDecimal().String(), nil 1544 case KindMysqlEnum: 1545 return d.GetMysqlEnum().String(), nil 1546 case KindMysqlSet: 1547 return d.GetMysqlSet().String(), nil 1548 case KindMysqlJSON: 1549 return d.GetMysqlJSON().String(), nil 1550 case KindBinaryLiteral, KindMysqlBit: 1551 return d.GetBinaryLiteral().ToString(), nil 1552 default: 1553 return "", errors.Errorf("cannot convert %v(type %T) to string", d.GetValue(), d.GetValue()) 1554 } 1555 } 1556 1557 // ToBytes gets the bytes representation of the datum. 1558 func (d *Datum) ToBytes() ([]byte, error) { 1559 switch d.k { 1560 case KindString, KindBytes: 1561 return d.GetBytes(), nil 1562 default: 1563 str, err := d.ToString() 1564 if err != nil { 1565 return nil, errors.Trace(err) 1566 } 1567 return []byte(str), nil 1568 } 1569 } 1570 1571 // ToMysqlJSON is similar to convertToMysqlJSON, except the 1572 // latter parses from string, but the former uses it as primitive. 1573 func (d *Datum) ToMysqlJSON() (j json.BinaryJSON, err error) { 1574 var in interface{} 1575 switch d.Kind() { 1576 case KindMysqlJSON: 1577 j = d.GetMysqlJSON() 1578 return 1579 case KindInt64: 1580 in = d.GetInt64() 1581 case KindUint64: 1582 in = d.GetUint64() 1583 case KindFloat32, KindFloat64: 1584 in = d.GetFloat64() 1585 case KindMysqlDecimal: 1586 in, err = d.GetMysqlDecimal().ToFloat64() 1587 case KindString, KindBytes: 1588 in = d.GetString() 1589 case KindBinaryLiteral, KindMysqlBit: 1590 in = d.GetBinaryLiteral().ToString() 1591 case KindNull: 1592 in = nil 1593 default: 1594 in, err = d.ToString() 1595 } 1596 if err != nil { 1597 err = errors.Trace(err) 1598 return 1599 } 1600 j = json.CreateBinary(in) 1601 return 1602 } 1603 1604 func invalidConv(d *Datum, tp byte) (Datum, error) { 1605 return Datum{}, errors.Errorf("cannot convert datum from %s to type %s.", KindStr(d.Kind()), TypeStr(tp)) 1606 } 1607 1608 func (d *Datum) convergeType(hasUint, hasDecimal, hasFloat *bool) (x Datum) { 1609 x = *d 1610 switch d.Kind() { 1611 case KindUint64: 1612 *hasUint = true 1613 case KindFloat32: 1614 f := d.GetFloat32() 1615 x.SetFloat64(float64(f)) 1616 *hasFloat = true 1617 case KindFloat64: 1618 *hasFloat = true 1619 case KindMysqlDecimal: 1620 *hasDecimal = true 1621 } 1622 return x 1623 } 1624 1625 // NewDatum creates a new Datum from an interface{}. 1626 func NewDatum(in interface{}) (d Datum) { 1627 switch x := in.(type) { 1628 case []interface{}: 1629 d.SetValue(MakeDatums(x...)) 1630 default: 1631 d.SetValue(in) 1632 } 1633 return d 1634 } 1635 1636 // NewIntDatum creates a new Datum from an int64 value. 1637 func NewIntDatum(i int64) (d Datum) { 1638 d.SetInt64(i) 1639 return d 1640 } 1641 1642 // NewUintDatum creates a new Datum from an uint64 value. 1643 func NewUintDatum(i uint64) (d Datum) { 1644 d.SetUint64(i) 1645 return d 1646 } 1647 1648 // NewBytesDatum creates a new Datum from a byte slice. 1649 func NewBytesDatum(b []byte) (d Datum) { 1650 d.SetBytes(b) 1651 return d 1652 } 1653 1654 // NewStringDatum creates a new Datum from a string. 1655 func NewStringDatum(s string) (d Datum) { 1656 d.SetString(s) 1657 return d 1658 } 1659 1660 // NewFloat64Datum creates a new Datum from a float64 value. 1661 func NewFloat64Datum(f float64) (d Datum) { 1662 d.SetFloat64(f) 1663 return d 1664 } 1665 1666 // NewFloat32Datum creates a new Datum from a float32 value. 1667 func NewFloat32Datum(f float32) (d Datum) { 1668 d.SetFloat32(f) 1669 return d 1670 } 1671 1672 // NewDurationDatum creates a new Datum from a Duration value. 1673 func NewDurationDatum(dur Duration) (d Datum) { 1674 d.SetMysqlDuration(dur) 1675 return d 1676 } 1677 1678 // NewTimeDatum creates a new Time from a Time value. 1679 func NewTimeDatum(t Time) (d Datum) { 1680 d.SetMysqlTime(t) 1681 return d 1682 } 1683 1684 // NewDecimalDatum creates a new Datum form a MyDecimal value. 1685 func NewDecimalDatum(dec *MyDecimal) (d Datum) { 1686 d.SetMysqlDecimal(dec) 1687 return d 1688 } 1689 1690 // NewBinaryLiteralDatum creates a new BinaryLiteral Datum for a BinaryLiteral value. 1691 func NewBinaryLiteralDatum(b BinaryLiteral) (d Datum) { 1692 d.SetBinaryLiteral(b) 1693 return d 1694 } 1695 1696 // NewMysqlBitDatum creates a new MysqlBit Datum for a BinaryLiteral value. 1697 func NewMysqlBitDatum(b BinaryLiteral) (d Datum) { 1698 d.SetMysqlBit(b) 1699 return d 1700 } 1701 1702 // NewMysqlEnumDatum creates a new MysqlEnum Datum for a Enum value. 1703 func NewMysqlEnumDatum(e Enum) (d Datum) { 1704 d.SetMysqlEnum(e) 1705 return d 1706 } 1707 1708 // MakeDatums creates datum slice from interfaces. 1709 func MakeDatums(args ...interface{}) []Datum { 1710 datums := make([]Datum, len(args)) 1711 for i, v := range args { 1712 datums[i] = NewDatum(v) 1713 } 1714 return datums 1715 } 1716 1717 // MinNotNullDatum returns a datum represents minimum not null value. 1718 func MinNotNullDatum() Datum { 1719 return Datum{k: KindMinNotNull} 1720 } 1721 1722 // MaxValueDatum returns a datum represents max value. 1723 func MaxValueDatum() Datum { 1724 return Datum{k: KindMaxValue} 1725 } 1726 1727 // EqualDatums compare if a and b contains the same datum values. 1728 func EqualDatums(sc *stmtctx.StatementContext, a []Datum, b []Datum) (bool, error) { 1729 if len(a) != len(b) { 1730 return false, nil 1731 } 1732 if a == nil && b == nil { 1733 return true, nil 1734 } 1735 if a == nil || b == nil { 1736 return false, nil 1737 } 1738 for i, ai := range a { 1739 v, err := ai.CompareDatum(sc, &b[i]) 1740 if err != nil { 1741 return false, errors.Trace(err) 1742 } 1743 if v != 0 { 1744 return false, nil 1745 } 1746 } 1747 return true, nil 1748 } 1749 1750 // SortDatums sorts a slice of datum. 1751 func SortDatums(sc *stmtctx.StatementContext, datums []Datum) error { 1752 sorter := datumsSorter{datums: datums, sc: sc} 1753 sort.Sort(&sorter) 1754 return sorter.err 1755 } 1756 1757 type datumsSorter struct { 1758 datums []Datum 1759 sc *stmtctx.StatementContext 1760 err error 1761 } 1762 1763 func (ds *datumsSorter) Len() int { 1764 return len(ds.datums) 1765 } 1766 1767 func (ds *datumsSorter) Less(i, j int) bool { 1768 cmp, err := ds.datums[i].CompareDatum(ds.sc, &ds.datums[j]) 1769 if err != nil { 1770 ds.err = errors.Trace(err) 1771 return true 1772 } 1773 return cmp < 0 1774 } 1775 1776 func (ds *datumsSorter) Swap(i, j int) { 1777 ds.datums[i], ds.datums[j] = ds.datums[j], ds.datums[i] 1778 } 1779 1780 func handleTruncateError(sc *stmtctx.StatementContext) error { 1781 if sc.IgnoreTruncate { 1782 return nil 1783 } 1784 if !sc.TruncateAsWarning { 1785 return ErrTruncated 1786 } 1787 sc.AppendWarning(ErrTruncated) 1788 return nil 1789 } 1790 1791 // DatumsToString converts several datums to formatted string. 1792 func DatumsToString(datums []Datum, handleSpecialValue bool) (string, error) { 1793 var strs []string 1794 for _, datum := range datums { 1795 if handleSpecialValue { 1796 switch datum.Kind() { 1797 case KindNull: 1798 strs = append(strs, "NULL") 1799 continue 1800 case KindMinNotNull: 1801 strs = append(strs, "-inf") 1802 continue 1803 case KindMaxValue: 1804 strs = append(strs, "+inf") 1805 continue 1806 } 1807 } 1808 str, err := datum.ToString() 1809 if err != nil { 1810 return "", errors.Trace(err) 1811 } 1812 strs = append(strs, str) 1813 } 1814 size := len(datums) 1815 if size > 1 { 1816 strs[0] = "(" + strs[0] 1817 strs[size-1] = strs[size-1] + ")" 1818 } 1819 return strings.Join(strs, ", "), nil 1820 } 1821 1822 // DatumsToStrNoErr converts some datums to a formatted string. 1823 // If an error occurs, it will print a log instead of returning an error. 1824 func DatumsToStrNoErr(datums []Datum) string { 1825 str, err := DatumsToString(datums, true) 1826 terror.Log(errors.Trace(err)) 1827 return str 1828 } 1829 1830 // CopyDatum returns a new copy of the datum. 1831 // TODO: Abandon this function. 1832 func CopyDatum(datum Datum) Datum { 1833 return *datum.Copy() 1834 } 1835 1836 // CopyRow deep copies a Datum slice. 1837 func CopyRow(dr []Datum) []Datum { 1838 c := make([]Datum, len(dr)) 1839 for i, d := range dr { 1840 c[i] = *d.Copy() 1841 } 1842 return c 1843 }