github.com/pingcap/tidb/parser@v0.0.0-20231013125129-93a834a6bf8d/test_driver/test_driver_datum.go (about) 1 // Copyright 2019 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 //go:build !codes 15 // +build !codes 16 17 package test_driver 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 "fmt" 23 "math" 24 "strconv" 25 "strings" 26 27 "github.com/pingcap/errors" 28 "github.com/pingcap/tidb/parser/charset" 29 "github.com/pingcap/tidb/parser/mysql" 30 "github.com/pingcap/tidb/parser/types" 31 ) 32 33 // Kind constants. 34 const ( 35 KindNull byte = 0 36 KindInt64 byte = 1 37 KindUint64 byte = 2 38 KindFloat32 byte = 3 39 KindFloat64 byte = 4 40 KindString byte = 5 41 KindBytes byte = 6 42 KindBinaryLiteral byte = 7 // Used for BIT / HEX literals. 43 KindMysqlDecimal byte = 8 44 KindMysqlDuration byte = 9 45 KindMysqlEnum byte = 10 46 KindMysqlBit byte = 11 // Used for BIT table column values. 47 KindMysqlSet byte = 12 48 KindMysqlTime byte = 13 49 KindInterface byte = 14 50 KindMinNotNull byte = 15 51 KindMaxValue byte = 16 52 KindRaw byte = 17 53 KindMysqlJSON byte = 18 54 ) 55 56 // Datum is a data box holds different kind of data. 57 // It has better performance and is easier to use than `interface{}`. 58 type Datum struct { 59 k byte // datum kind. 60 i int64 // i can hold int64 uint64 float64 values. 61 b []byte // b can hold string or []byte values. 62 x interface{} // x hold all other types. 63 } 64 65 // Kind gets the kind of the datum. 66 func (d *Datum) Kind() byte { 67 return d.k 68 } 69 70 // GetInt64 gets int64 value. 71 func (d *Datum) GetInt64() int64 { 72 return d.i 73 } 74 75 // SetInt64 sets int64 value. 76 func (d *Datum) SetInt64(i int64) { 77 d.k = KindInt64 78 d.i = i 79 } 80 81 // GetUint64 gets uint64 value. 82 func (d *Datum) GetUint64() uint64 { 83 return uint64(d.i) 84 } 85 86 // SetUint64 sets uint64 value. 87 func (d *Datum) SetUint64(i uint64) { 88 d.k = KindUint64 89 d.i = int64(i) 90 } 91 92 // GetFloat64 gets float64 value. 93 func (d *Datum) GetFloat64() float64 { 94 return math.Float64frombits(uint64(d.i)) 95 } 96 97 // SetFloat64 sets float64 value. 98 func (d *Datum) SetFloat64(f float64) { 99 d.k = KindFloat64 100 d.i = int64(math.Float64bits(f)) 101 } 102 103 // GetFloat32 gets float32 value. 104 func (d *Datum) GetFloat32() float32 { 105 return float32(math.Float64frombits(uint64(d.i))) 106 } 107 108 // SetFloat32 sets float32 value. 109 func (d *Datum) SetFloat32(f float32) { 110 d.k = KindFloat32 111 d.i = int64(math.Float64bits(float64(f))) 112 } 113 114 // GetString gets string value. 115 func (d *Datum) GetString() string { 116 return string(d.b) 117 } 118 119 // SetString sets string value. 120 func (d *Datum) SetString(s string) { 121 d.k = KindString 122 d.b = []byte(s) 123 } 124 125 // GetBytes gets bytes value. 126 func (d *Datum) GetBytes() []byte { 127 return d.b 128 } 129 130 // SetBytes sets bytes value to datum. 131 func (d *Datum) SetBytes(b []byte) { 132 d.k = KindBytes 133 d.b = b 134 } 135 136 // SetBytesAsString sets bytes value to datum as string type. 137 func (d *Datum) SetBytesAsString(b []byte) { 138 d.k = KindString 139 d.b = b 140 } 141 142 // GetInterface gets interface value. 143 func (d *Datum) GetInterface() interface{} { 144 return d.x 145 } 146 147 // SetInterface sets interface to datum. 148 func (d *Datum) SetInterface(x interface{}) { 149 d.k = KindInterface 150 d.x = x 151 } 152 153 // SetNull sets datum to nil. 154 func (d *Datum) SetNull() { 155 d.k = KindNull 156 d.x = nil 157 } 158 159 // GetBinaryLiteral gets Bit value 160 func (d *Datum) GetBinaryLiteral() BinaryLiteral { 161 return d.b 162 } 163 164 // SetBinaryLiteral sets Bit value 165 func (d *Datum) SetBinaryLiteral(b BinaryLiteral) { 166 d.k = KindBinaryLiteral 167 d.b = b 168 } 169 170 // GetMysqlDecimal gets decimal value 171 func (d *Datum) GetMysqlDecimal() *MyDecimal { 172 return d.x.(*MyDecimal) 173 } 174 175 // SetMysqlDecimal sets decimal value 176 func (d *Datum) SetMysqlDecimal(b *MyDecimal) { 177 d.k = KindMysqlDecimal 178 d.x = b 179 } 180 181 // GetValue gets the value of the datum of any kind. 182 func (d *Datum) GetValue() interface{} { 183 switch d.k { 184 case KindInt64: 185 return d.GetInt64() 186 case KindUint64: 187 return d.GetUint64() 188 case KindFloat32: 189 return d.GetFloat32() 190 case KindFloat64: 191 return d.GetFloat64() 192 case KindString: 193 return d.GetString() 194 case KindBytes: 195 return d.GetBytes() 196 case KindMysqlDecimal: 197 return d.GetMysqlDecimal() 198 case KindBinaryLiteral, KindMysqlBit: 199 return d.GetBinaryLiteral() 200 default: 201 return d.GetInterface() 202 } 203 } 204 205 // SetValue sets any kind of value. 206 func (d *Datum) SetValue(val interface{}) { 207 switch x := val.(type) { 208 case nil: 209 d.SetNull() 210 case bool: 211 if x { 212 d.SetInt64(1) 213 } else { 214 d.SetInt64(0) 215 } 216 case int: 217 d.SetInt64(int64(x)) 218 case int64: 219 d.SetInt64(x) 220 case uint64: 221 d.SetUint64(x) 222 case float32: 223 d.SetFloat32(x) 224 case float64: 225 d.SetFloat64(x) 226 case string: 227 d.SetString(x) 228 case []byte: 229 d.SetBytes(x) 230 case *MyDecimal: 231 d.SetMysqlDecimal(x) 232 case BinaryLiteral: 233 d.SetBinaryLiteral(x) 234 case BitLiteral: // Store as BinaryLiteral for Bit and Hex literals 235 d.SetBinaryLiteral(BinaryLiteral(x)) 236 case HexLiteral: 237 d.SetBinaryLiteral(BinaryLiteral(x)) 238 default: 239 d.SetInterface(x) 240 } 241 } 242 243 // NewDatum creates a new Datum from an interface{}. 244 func NewDatum(in interface{}) (d Datum) { 245 switch x := in.(type) { 246 case []interface{}: 247 d.SetValue(MakeDatums(x...)) 248 default: 249 d.SetValue(in) 250 } 251 return d 252 } 253 254 // NewBytesDatum creates a new Datum from a byte slice. 255 func NewBytesDatum(b []byte) (d Datum) { 256 d.SetBytes(b) 257 return d 258 } 259 260 // NewStringDatum creates a new Datum from a string. 261 func NewStringDatum(s string) (d Datum) { 262 d.SetString(s) 263 return d 264 } 265 266 // MakeDatums creates datum slice from interfaces. 267 func MakeDatums(args ...interface{}) []Datum { 268 datums := make([]Datum, len(args)) 269 for i, v := range args { 270 datums[i] = NewDatum(v) 271 } 272 return datums 273 } 274 275 // BinaryLiteral is the internal type for storing bit / hex literal type. 276 type BinaryLiteral []byte 277 278 // BitLiteral is the bit literal type. 279 type BitLiteral BinaryLiteral 280 281 // HexLiteral is the hex literal type. 282 type HexLiteral BinaryLiteral 283 284 // ZeroBinaryLiteral is a BinaryLiteral literal with zero value. 285 var ZeroBinaryLiteral = BinaryLiteral{} 286 287 // String implements fmt.Stringer interface. 288 func (b BinaryLiteral) String() string { 289 if len(b) == 0 { 290 return "" 291 } 292 return "0x" + hex.EncodeToString(b) 293 } 294 295 // ToString returns the string representation for the literal. 296 func (b BinaryLiteral) ToString() string { 297 return string(b) 298 } 299 300 // ToBitLiteralString returns the bit literal representation for the literal. 301 func (b BinaryLiteral) ToBitLiteralString(trimLeadingZero bool) string { 302 if len(b) == 0 { 303 return "b''" 304 } 305 var buf bytes.Buffer 306 for _, data := range b { 307 fmt.Fprintf(&buf, "%08b", data) 308 } 309 ret := buf.Bytes() 310 if trimLeadingZero { 311 ret = bytes.TrimLeft(ret, "0") 312 if len(ret) == 0 { 313 ret = []byte{'0'} 314 } 315 } 316 return fmt.Sprintf("b'%s'", string(ret)) 317 } 318 319 // ParseBitStr parses bit string. 320 // The string format can be b'val', B'val' or 0bval, val must be 0 or 1. 321 // See https://dev.mysql.com/doc/refman/5.7/en/bit-value-literals.html 322 func ParseBitStr(s string) (BinaryLiteral, error) { 323 if len(s) == 0 { 324 return nil, errors.Errorf("invalid empty string for parsing bit type") 325 } 326 327 if s[0] == 'b' || s[0] == 'B' { 328 // format is b'val' or B'val' 329 s = strings.Trim(s[1:], "'") 330 } else if strings.HasPrefix(s, "0b") { 331 s = s[2:] 332 } else { 333 // here means format is not b'val', B'val' or 0bval. 334 return nil, errors.Errorf("invalid bit type format %s", s) 335 } 336 337 if len(s) == 0 { 338 return ZeroBinaryLiteral, nil 339 } 340 341 alignedLength := (len(s) + 7) &^ 7 342 s = ("00000000" + s)[len(s)+8-alignedLength:] // Pad with zero (slice from `-alignedLength`) 343 byteLength := len(s) >> 3 344 buf := make([]byte, byteLength) 345 346 for i := 0; i < byteLength; i++ { 347 strPosition := i << 3 348 val, err := strconv.ParseUint(s[strPosition:strPosition+8], 2, 8) 349 if err != nil { 350 return nil, errors.Trace(err) 351 } 352 buf[i] = byte(val) 353 } 354 355 return buf, nil 356 } 357 358 // NewBitLiteral parses bit string as BitLiteral type. 359 func NewBitLiteral(s string) (BitLiteral, error) { 360 b, err := ParseBitStr(s) 361 if err != nil { 362 return BitLiteral{}, err 363 } 364 return BitLiteral(b), nil 365 } 366 367 // ToString implement ast.BinaryLiteral interface 368 func (b BitLiteral) ToString() string { 369 return BinaryLiteral(b).ToString() 370 } 371 372 // ParseHexStr parses hexadecimal string literal. 373 // See https://dev.mysql.com/doc/refman/5.7/en/hexadecimal-literals.html 374 func ParseHexStr(s string) (BinaryLiteral, error) { 375 if len(s) == 0 { 376 return nil, errors.Errorf("invalid empty string for parsing hexadecimal literal") 377 } 378 379 if s[0] == 'x' || s[0] == 'X' { 380 // format is x'val' or X'val' 381 s = strings.Trim(s[1:], "'") 382 if len(s)%2 != 0 { 383 return nil, errors.Errorf("invalid hexadecimal format, must even numbers, but %d", len(s)) 384 } 385 } else if strings.HasPrefix(s, "0x") { 386 s = s[2:] 387 } else { 388 // here means format is not x'val', X'val' or 0xval. 389 return nil, errors.Errorf("invalid hexadecimal format %s", s) 390 } 391 392 if len(s) == 0 { 393 return ZeroBinaryLiteral, nil 394 } 395 396 if len(s)%2 != 0 { 397 s = "0" + s 398 } 399 buf, err := hex.DecodeString(s) 400 if err != nil { 401 return nil, errors.Trace(err) 402 } 403 return buf, nil 404 } 405 406 // NewHexLiteral parses hexadecimal string as HexLiteral type. 407 func NewHexLiteral(s string) (HexLiteral, error) { 408 h, err := ParseHexStr(s) 409 if err != nil { 410 return HexLiteral{}, err 411 } 412 return HexLiteral(h), nil 413 } 414 415 // ToString implement ast.BinaryLiteral interface 416 func (b HexLiteral) ToString() string { 417 return BinaryLiteral(b).ToString() 418 } 419 420 // SetBinChsClnFlag sets charset, collation as 'binary' and adds binaryFlag to FieldType. 421 func SetBinChsClnFlag(ft *types.FieldType) { 422 ft.SetCharset(charset.CharsetBin) 423 ft.SetCollate(charset.CollationBin) 424 ft.AddFlag(mysql.BinaryFlag) 425 } 426 427 // DefaultFsp is the default digit of fractional seconds part. 428 // MySQL use 0 as the default Fsp. 429 const DefaultFsp = int8(0) 430 431 // DefaultTypeForValue returns the default FieldType for the value. 432 func DefaultTypeForValue(value interface{}, tp *types.FieldType, charset string, collate string) { 433 switch x := value.(type) { 434 case nil: 435 tp.SetType(mysql.TypeNull) 436 tp.SetFlen(0) 437 tp.SetDecimal(0) 438 SetBinChsClnFlag(tp) 439 case bool: 440 tp.SetType(mysql.TypeLonglong) 441 tp.SetFlen(1) 442 tp.SetDecimal(0) 443 tp.AddFlag(mysql.IsBooleanFlag) 444 SetBinChsClnFlag(tp) 445 case int: 446 tp.SetType(mysql.TypeLonglong) 447 tp.SetFlen(StrLenOfInt64Fast(int64(x))) 448 tp.SetDecimal(0) 449 SetBinChsClnFlag(tp) 450 case int64: 451 tp.SetType(mysql.TypeLonglong) 452 tp.SetFlen(StrLenOfInt64Fast(x)) 453 tp.SetDecimal(0) 454 SetBinChsClnFlag(tp) 455 case uint64: 456 tp.SetType(mysql.TypeLonglong) 457 tp.AddFlag(mysql.UnsignedFlag) 458 tp.SetFlen(StrLenOfUint64Fast(x)) 459 tp.SetDecimal(0) 460 SetBinChsClnFlag(tp) 461 case string: 462 tp.SetType(mysql.TypeVarString) 463 // TODO: tp.flen should be len(x) * 3 (max bytes length of CharsetUTF8) 464 tp.SetFlen(len(x)) 465 tp.SetDecimal(types.UnspecifiedLength) 466 tp.SetCharset(charset) 467 tp.SetCollate(collate) 468 case float32: 469 tp.SetType(mysql.TypeFloat) 470 s := strconv.FormatFloat(float64(x), 'f', -1, 32) 471 tp.SetFlen(len(s)) 472 tp.SetDecimal(types.UnspecifiedLength) 473 SetBinChsClnFlag(tp) 474 case float64: 475 tp.SetType(mysql.TypeDouble) 476 s := strconv.FormatFloat(x, 'f', -1, 64) 477 tp.SetFlen(len(s)) 478 tp.SetDecimal(types.UnspecifiedLength) 479 SetBinChsClnFlag(tp) 480 case []byte: 481 tp.SetType(mysql.TypeBlob) 482 tp.SetFlen(len(x)) 483 tp.SetDecimal(types.UnspecifiedLength) 484 SetBinChsClnFlag(tp) 485 case BitLiteral: 486 tp.SetType(mysql.TypeVarString) 487 tp.SetFlen(len(x)) 488 tp.SetDecimal(0) 489 SetBinChsClnFlag(tp) 490 case HexLiteral: 491 tp.SetType(mysql.TypeVarString) 492 tp.SetFlen(len(x) * 3) 493 tp.SetDecimal(0) 494 tp.AddFlag(mysql.UnsignedFlag) 495 SetBinChsClnFlag(tp) 496 case BinaryLiteral: 497 tp.SetType(mysql.TypeBit) 498 tp.SetFlen(len(x) * 8) 499 tp.SetDecimal(0) 500 SetBinChsClnFlag(tp) 501 tp.DelFlag(mysql.BinaryFlag) 502 tp.AddFlag(mysql.UnsignedFlag) 503 case *MyDecimal: 504 tp.SetType(mysql.TypeNewDecimal) 505 tp.SetFlen(len(x.ToString())) 506 tp.SetDecimal(int(x.digitsFrac)) 507 SetBinChsClnFlag(tp) 508 default: 509 tp.SetType(mysql.TypeUnspecified) 510 tp.SetFlen(types.UnspecifiedLength) 511 tp.SetDecimal(types.UnspecifiedLength) 512 } 513 }