github.com/XiaoMi/Gaea@v1.2.5/mysql/encoding.go (about) 1 /* 2 Copyright 2017 Google Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreedto in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Copyright 2019 The Gaea Authors. All Rights Reserved. 18 // 19 // Licensed under the Apache License, Version 2.0 (the "License"); 20 // you may not use this file except in compliance with the License. 21 // You may obtain a copy of the License at 22 // 23 // http://www.apache.org/licenses/LICENSE-2.0 24 // 25 // Unless required by applicable law or agreed to in writing, software 26 // distributed under the License is distributed on an "AS IS" BASIS, 27 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 // See the License for the specific language governing permissions and 29 // limitations under the License. 30 31 package mysql 32 33 import ( 34 "bytes" 35 "encoding/binary" 36 "fmt" 37 "math" 38 "strconv" 39 "time" 40 41 "github.com/XiaoMi/Gaea/util/hack" 42 ) 43 44 // This file contains the data encoding and decoding functions. 45 46 // 47 // Encoding methods. 48 // 49 // The same assumptions are made for all the encoding functions: 50 // - there is enough space to write the data in the buffer. If not, we 51 // will panic with out of bounds. 52 // - all functions start writing at 'pos' in the buffer, and return the next position. 53 54 // LenEncIntSize returns the number of bytes required to encode a 55 // variable-length integer. 56 func LenEncIntSize(i uint64) int { 57 switch { 58 case i < 251: 59 return 1 60 case i < 1<<16: 61 return 3 62 case i < 1<<24: 63 return 4 64 default: 65 return 9 66 } 67 } 68 69 // WriteLenEncInt write uint64 to []byte 70 func WriteLenEncInt(data []byte, pos int, i uint64) int { 71 switch { 72 case i < 251: 73 data[pos] = byte(i) 74 return pos + 1 75 case i < 1<<16: 76 data[pos] = 0xfc 77 data[pos+1] = byte(i) 78 data[pos+2] = byte(i >> 8) 79 return pos + 3 80 case i < 1<<24: 81 data[pos] = 0xfd 82 data[pos+1] = byte(i) 83 data[pos+2] = byte(i >> 8) 84 data[pos+3] = byte(i >> 16) 85 return pos + 4 86 default: 87 data[pos] = 0xfe 88 data[pos+1] = byte(i) 89 data[pos+2] = byte(i >> 8) 90 data[pos+3] = byte(i >> 16) 91 data[pos+4] = byte(i >> 24) 92 data[pos+5] = byte(i >> 32) 93 data[pos+6] = byte(i >> 40) 94 data[pos+7] = byte(i >> 48) 95 data[pos+8] = byte(i >> 56) 96 return pos + 9 97 } 98 } 99 100 // AppendLenEncInt append LenEncInt []byte to data 101 func AppendLenEncInt(data []byte, i uint64) []byte { 102 switch { 103 case i <= 250: 104 return append(data, byte(i)) 105 106 case i <= 0xffff: 107 return append(data, 0xfc, byte(i), byte(i>>8)) 108 109 case i <= 0xffffff: 110 return append(data, 0xfd, byte(i), byte(i>>8), byte(i>>16)) 111 112 case i <= 0xffffffffffffffff: 113 return append(data, 0xfe, byte(i), byte(i>>8), byte(i>>16), byte(i>>24), 114 byte(i>>32), byte(i>>40), byte(i>>48), byte(i>>56)) 115 } 116 117 return data 118 } 119 120 // LenNullString return lenght Null terminated string 121 func LenNullString(value string) int { 122 return len(value) + 1 123 } 124 125 // WriteNullString write NULL terminated strign to []byte 126 func WriteNullString(data []byte, pos int, value string) int { 127 pos += copy(data[pos:], value) 128 data[pos] = 0 129 return pos + 1 130 } 131 132 func writeEOFString(data []byte, pos int, value string) int { 133 pos += copy(data[pos:], value) 134 return pos 135 } 136 137 // WriteByte write byte to []byte 138 func WriteByte(data []byte, pos int, value byte) int { 139 data[pos] = value 140 return pos + 1 141 } 142 143 // WriteBytes write byte to []byte 144 func WriteBytes(data []byte, pos int, value []byte) int { 145 pos += copy(data[pos:], value) 146 return pos 147 } 148 149 // WriteUint16 write uint16 to []byte 150 func WriteUint16(data []byte, pos int, value uint16) int { 151 data[pos] = byte(value) 152 data[pos+1] = byte(value >> 8) 153 return pos + 2 154 } 155 156 // AppendUint16 append uint16 to []byte 157 func AppendUint16(data []byte, n uint16) []byte { 158 data = append(data, byte(n)) 159 data = append(data, byte(n>>8)) 160 return data 161 } 162 163 // WriteUint32 write uint32 to []byte 164 func WriteUint32(data []byte, pos int, value uint32) int { 165 data[pos] = byte(value) 166 data[pos+1] = byte(value >> 8) 167 data[pos+2] = byte(value >> 16) 168 data[pos+3] = byte(value >> 24) 169 return pos + 4 170 } 171 172 // AppendUint32 append uint32 to []byte 173 func AppendUint32(data []byte, n uint32) []byte { 174 data = append(data, byte(n)) 175 data = append(data, byte(n>>8)) 176 data = append(data, byte(n>>16)) 177 data = append(data, byte(n>>24)) 178 return data 179 } 180 181 // WriteUint64 write uint64 to []byte 182 func WriteUint64(data []byte, pos int, value uint64) int { 183 data[pos] = byte(value) 184 data[pos+1] = byte(value >> 8) 185 data[pos+2] = byte(value >> 16) 186 data[pos+3] = byte(value >> 24) 187 data[pos+4] = byte(value >> 32) 188 data[pos+5] = byte(value >> 40) 189 data[pos+6] = byte(value >> 48) 190 data[pos+7] = byte(value >> 56) 191 return pos + 8 192 } 193 194 // AppendUint64 append uint64 to []byte 195 func AppendUint64(data []byte, n uint64) []byte { 196 data = append(data, byte(n)) 197 data = append(data, byte(n>>8)) 198 data = append(data, byte(n>>16)) 199 data = append(data, byte(n>>24)) 200 data = append(data, byte(n>>32)) 201 data = append(data, byte(n>>40)) 202 data = append(data, byte(n>>48)) 203 data = append(data, byte(n>>56)) 204 return data 205 } 206 207 // LenEncStringSize calculate length of lenenc_str 208 // https://dev.mysql.com/doc/internals/en/describing-packets.html#type-lenenc_str 209 func LenEncStringSize(value string) int { 210 l := len(value) 211 return LenEncIntSize(uint64(l)) + l 212 } 213 214 // WriteLenEncString write string to []byte, return pos 215 func WriteLenEncString(data []byte, pos int, value string) int { 216 pos = WriteLenEncInt(data, pos, uint64(len(value))) 217 return writeEOFString(data, pos, value) 218 } 219 220 // AppendLenEncStringBytes append bytes of len enc string to data 221 func AppendLenEncStringBytes(data, b []byte) []byte { 222 data = AppendLenEncInt(data, uint64(len(b))) 223 data = append(data, b...) 224 return data 225 } 226 227 // WriteZeroes write 0 to []byte 228 func WriteZeroes(data []byte, pos int, len int) int { 229 for i := 0; i < len; i++ { 230 data[pos+i] = 0 231 } 232 return pos + len 233 } 234 235 // 236 // Decoding methods. 237 // 238 // The same assumptions are made for all the decoding functions: 239 // - they return the decode data, the new position to read from, and ak 'ok' flag. 240 // - all functions start reading at 'pos' in the buffer, and return the next position. 241 // 242 243 // ReadByte read one byte from []byte 244 func ReadByte(data []byte, pos int) (byte, int, bool) { 245 if pos >= len(data) { 246 return 0, 0, false 247 } 248 return data[pos], pos + 1, true 249 } 250 251 // ReadBytes read []byte from pos with sized size 252 func ReadBytes(data []byte, pos int, size int) ([]byte, int, bool) { 253 if pos+size-1 >= len(data) { 254 return nil, 0, false 255 } 256 return data[pos : pos+size], pos + size, true 257 } 258 259 // ReadBytesCopy returns a copy of the bytes in the packet. 260 // Useful to remember contents of ephemeral packets. 261 func ReadBytesCopy(data []byte, pos int, size int) ([]byte, int, bool) { 262 if pos+size-1 >= len(data) { 263 return nil, 0, false 264 } 265 result := make([]byte, size) 266 copy(result, data[pos:pos+size]) 267 return result, pos + size, true 268 } 269 270 // ReadNullString read Null terminated string from []byte, return string,pos,if end. 271 func ReadNullString(data []byte, pos int) (string, int, bool) { 272 end := bytes.IndexByte(data[pos:], 0) 273 if end == -1 { 274 return "", 0, false 275 } 276 return string(data[pos : pos+end]), pos + end + 1, true 277 } 278 279 // ReadNullString read Null terminated string from []byte, return byet,pos,if end. 280 func ReadNullByte(data []byte, pos int) ([]byte, int, bool) { 281 end := bytes.IndexByte(data[pos:], 0) 282 if end == -1 { 283 return []byte{}, 0, false 284 } 285 return data[pos : pos+end], pos + end + 1, true 286 } 287 288 // ReadUint16 read uint32 from []byte 289 func ReadUint16(data []byte, pos int) (uint16, int, bool) { 290 if pos+1 >= len(data) { 291 return 0, 0, false 292 } 293 return binary.LittleEndian.Uint16(data[pos : pos+2]), pos + 2, true 294 } 295 296 // ReadUint32 read uint32 from []byte 297 func ReadUint32(data []byte, pos int) (uint32, int, bool) { 298 if pos+3 >= len(data) { 299 return 0, 0, false 300 } 301 return binary.LittleEndian.Uint32(data[pos : pos+4]), pos + 4, true 302 } 303 304 // ReadUint64 read uint64 from []byte 305 func ReadUint64(data []byte, pos int) (uint64, int, bool) { 306 if pos+7 >= len(data) { 307 return 0, 0, false 308 } 309 return binary.LittleEndian.Uint64(data[pos : pos+8]), pos + 8, true 310 } 311 312 // ReadLenEncInt read info of len encoded int, return length, next pos(skip len self to data), is null, handle result 313 // https://dev.mysql.com/doc/internals/en/integer.html#packet-Protocol::FixedLengthInteger 314 func ReadLenEncInt(data []byte, pos int) (uint64, int, bool, bool) { 315 isNull := false 316 if pos >= len(data) { 317 return 0, 0, isNull, false 318 } 319 switch data[pos] { 320 // 251: NULL 321 case 0xfb: 322 isNull = true 323 return 0, pos + 1, isNull, true 324 case 0xfc: 325 // Encoded in the next 2 bytes. 326 if pos+2 >= len(data) { 327 return 0, 0, isNull, false 328 } 329 return uint64(data[pos+1]) | 330 uint64(data[pos+2])<<8, pos + 3, isNull, true 331 case 0xfd: 332 // Encoded in the next 3 bytes. 333 if pos+3 >= len(data) { 334 return 0, 0, isNull, false 335 } 336 return uint64(data[pos+1]) | 337 uint64(data[pos+2])<<8 | 338 uint64(data[pos+3])<<16, pos + 4, isNull, true 339 case 0xfe: 340 // Encoded in the next 8 bytes. 341 if pos+8 >= len(data) { 342 return 0, 0, isNull, false 343 } 344 return uint64(data[pos+1]) | 345 uint64(data[pos+2])<<8 | 346 uint64(data[pos+3])<<16 | 347 uint64(data[pos+4])<<24 | 348 uint64(data[pos+5])<<32 | 349 uint64(data[pos+6])<<40 | 350 uint64(data[pos+7])<<48 | 351 uint64(data[pos+8])<<56, pos + 9, isNull, true 352 } 353 // 0-250 354 return uint64(data[pos]), pos + 1, isNull, true 355 } 356 357 func readLenEncString(data []byte, pos int) (string, int, bool) { 358 size, pos, _, ok := ReadLenEncInt(data, pos) 359 if !ok { 360 return "", 0, false 361 } 362 s := int(size) 363 if pos+s-1 >= len(data) { 364 return "", 0, false 365 } 366 return string(data[pos : pos+s]), pos + s, true 367 } 368 369 // return next pos、handle result 370 func skipLenEncString(data []byte, pos int) (int, bool) { 371 size, pos, _, ok := ReadLenEncInt(data, pos) 372 if !ok { 373 return 0, false 374 } 375 s := int(size) 376 if pos+s-1 >= len(data) { 377 return 0, false 378 } 379 return pos + s, true 380 } 381 382 // ReadLenEncStringAsBytes read len encoded string, return []byte format, next pos, is null, handle result 383 func ReadLenEncStringAsBytes(data []byte, pos int) ([]byte, int, bool, bool) { 384 size, pos, isNull, ok := ReadLenEncInt(data, pos) 385 if !ok { 386 return nil, 0, isNull, false 387 } 388 s := int(size) 389 if pos+s-1 >= len(data) { 390 return nil, 0, isNull, false 391 } 392 return data[pos : pos+s], pos + s, isNull, true 393 } 394 395 // FormatBinaryDate format binary date type 396 func FormatBinaryDate(n int, data []byte) ([]byte, error) { 397 switch n { 398 case 0: 399 return []byte("0000-00-00"), nil 400 case 4: 401 return []byte(fmt.Sprintf("%04d-%02d-%02d", 402 binary.LittleEndian.Uint16(data[:2]), 403 data[2], 404 data[3])), nil 405 default: 406 return nil, fmt.Errorf("invalid date packet length %d", n) 407 } 408 } 409 410 // FormatBinaryDateTime format binary datetime type 411 func FormatBinaryDateTime(n int, data []byte) ([]byte, error) { 412 switch n { 413 case 0: 414 return []byte("0000-00-00 00:00:00"), nil 415 case 4: 416 return []byte(fmt.Sprintf("%04d-%02d-%02d 00:00:00", 417 binary.LittleEndian.Uint16(data[:2]), 418 data[2], 419 data[3])), nil 420 case 7: 421 return []byte(fmt.Sprintf( 422 "%04d-%02d-%02d %02d:%02d:%02d", 423 binary.LittleEndian.Uint16(data[:2]), 424 data[2], 425 data[3], 426 data[4], 427 data[5], 428 data[6])), nil 429 case 11: 430 return []byte(fmt.Sprintf( 431 "%04d-%02d-%02d %02d:%02d:%02d.%06d", 432 binary.LittleEndian.Uint16(data[:2]), 433 data[2], 434 data[3], 435 data[4], 436 data[5], 437 data[6], 438 binary.LittleEndian.Uint32(data[7:11]))), nil 439 default: 440 return nil, fmt.Errorf("invalid datetime packet length %d", n) 441 } 442 } 443 444 // FormatBinaryTime format binary time type 445 func FormatBinaryTime(n int, data []byte) ([]byte, error) { 446 if n == 0 { 447 return []byte("0000-00-00"), nil 448 } 449 450 var sign byte 451 if data[0] == 1 { 452 sign = byte('-') 453 } 454 455 switch n { 456 case 8: 457 return []byte(fmt.Sprintf( 458 "%c%02d:%02d:%02d", 459 sign, 460 uint16(data[1])*24+uint16(data[5]), 461 data[6], 462 data[7], 463 )), nil 464 case 12: 465 return []byte(fmt.Sprintf( 466 "%c%02d:%02d:%02d.%06d", 467 sign, 468 uint16(data[1])*24+uint16(data[5]), 469 data[6], 470 data[7], 471 binary.LittleEndian.Uint32(data[8:12]), 472 )), nil 473 default: 474 return nil, fmt.Errorf("invalid time packet length %d", n) 475 } 476 } 477 478 // AppendBinaryValue encode binary-type value of prepare binary protocol according to type of value 479 func AppendBinaryValue(data []byte, fieldType uint8, value interface{}) ([]byte, error) { 480 // constructor phase 481 var t []byte 482 switch v := value.(type) { 483 case int8: 484 t = make([]byte, 8) 485 WriteUint64(t, 0, uint64(v)) 486 case int16: 487 t = make([]byte, 8) 488 WriteUint64(t, 0, uint64(v)) 489 case int32: 490 t = make([]byte, 8) 491 WriteUint64(t, 0, uint64(v)) 492 case int64: 493 t = make([]byte, 8) 494 WriteUint64(t, 0, uint64(v)) 495 case int: 496 t = make([]byte, 8) 497 WriteUint64(t, 0, uint64(v)) 498 case uint8: 499 t = make([]byte, 8) 500 WriteUint64(t, 0, uint64(v)) 501 case uint16: 502 t = make([]byte, 8) 503 WriteUint64(t, 0, uint64(v)) 504 case uint32: 505 t = make([]byte, 8) 506 WriteUint64(t, 0, uint64(v)) 507 case uint64: 508 t = make([]byte, 8) 509 WriteUint64(t, 0, uint64(v)) 510 case uint: 511 t = make([]byte, 8) 512 WriteUint64(t, 0, uint64(v)) 513 case float64: 514 switch fieldType { 515 case TypeFloat: 516 t = make([]byte, 4) 517 WriteUint32(t, 0, math.Float32bits(float32(v))) 518 case TypeNewDecimal: 519 tmp := strconv.FormatFloat(v, 'f', -1, 64) 520 t = []byte(tmp) 521 default: 522 t = make([]byte, 8) 523 WriteUint64(t, 0, math.Float64bits(v)) 524 } 525 case []byte: 526 t = v 527 case string: 528 switch fieldType { 529 case TypeDatetime, TypeTimestamp: 530 if v == "0000-00-00 00:00:00" { 531 t = append(t, 0) 532 } else { 533 ts, err := time.Parse("2006-01-02 15:04:05", v) 534 if err != nil { 535 var mysqlTypeStr string 536 if fieldType == TypeDatetime { 537 mysqlTypeStr = "TypeDatetime" 538 } else { 539 mysqlTypeStr = "TypeTimestamp" 540 } 541 return nil, fmt.Errorf("invalid %s %s", mysqlTypeStr, v) 542 } 543 544 t = append(t, 11) 545 t = AppendUint16(t, uint16(ts.Year())) 546 t = append(t, byte(int(ts.Month())), byte(ts.Day()), byte(ts.Hour()), byte(ts.Minute()), byte(ts.Second())) 547 microseconds := uint32(ts.Nanosecond() / 1000) 548 t = AppendUint32(t, microseconds) 549 } 550 case TypeDate: 551 // format: 2006-01-02 552 ts, err := time.Parse("2006-01-02", v) 553 if err != nil { 554 t = append(t, 0) 555 } else { 556 t = append(t, 4) 557 t = AppendUint16(t, uint16(ts.Year())) 558 t = append(t, byte(int(ts.Month())), byte(ts.Day())) 559 } 560 case TypeDuration: 561 timeValue, err := stringToMysqlTime(v) 562 if err != nil { 563 return nil, err 564 } 565 566 t = mysqlTimeToBinaryResult(timeValue) 567 default: 568 t = hack.Slice(v) 569 } 570 default: 571 return data, fmt.Errorf("invalid type %T", value) 572 } 573 574 // append phase 575 switch fieldType { 576 case TypeTiny: 577 data = append(data, t[0]) 578 return data, nil 579 case TypeShort, TypeYear: 580 data = append(data, t[:2]...) 581 return data, nil 582 case TypeFloat, TypeInt24, TypeLong: 583 data = append(data, t[:4]...) 584 return data, nil 585 case TypeLonglong, TypeDouble: 586 data = append(data, t[:8]...) 587 return data, nil 588 case TypeNewDecimal, TypeJSON, TypeString, TypeVarString, TypeVarchar, TypeBit, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob: 589 tmp := make([]byte, 0, len(t)+9) 590 data = append(data, AppendLenEncStringBytes(tmp, t)...) 591 return data, nil 592 case TypeEnum, TypeSet, TypeDate, TypeDatetime, TypeDuration, TypeTimestamp, TypeNewDate: 593 data = append(data, t...) 594 return data, nil 595 default: 596 return data, fmt.Errorf("not supported field type") 597 } 598 }