vitess.io/vitess@v0.16.2/go/mysql/binlog_event_rbr.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 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 agreed to 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 package mysql 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "math" 24 "strconv" 25 "strings" 26 "time" 27 28 "vitess.io/vitess/go/sqltypes" 29 "vitess.io/vitess/go/vt/proto/vtrpc" 30 "vitess.io/vitess/go/vt/vterrors" 31 32 querypb "vitess.io/vitess/go/vt/proto/query" 33 ) 34 35 // ZeroTimestamp is the special value 0 for a timestamp. 36 var ZeroTimestamp = []byte("0000-00-00 00:00:00") 37 38 // TableMap implements BinlogEvent.TableMap(). 39 // 40 // Expected format (L = total length of event data): 41 // 42 // # bytes field 43 // 4/6 table id 44 // 2 flags 45 // 1 schema name length sl 46 // sl schema name 47 // 1 [00] 48 // 1 table name length tl 49 // tl table name 50 // 1 [00] 51 // <var> column count cc (var-len encoded) 52 // cc column-def, one byte per column 53 // <var> column-meta-def (var-len encoded string) 54 // n NULL-bitmask, length: (cc + 7) / 8 55 func (ev binlogEvent) TableMap(f BinlogFormat) (*TableMap, error) { 56 data := ev.Bytes()[f.HeaderLength:] 57 58 result := &TableMap{} 59 pos := 6 60 if f.HeaderSize(eTableMapEvent) == 6 { 61 pos = 4 62 } 63 result.Flags = binary.LittleEndian.Uint16(data[pos : pos+2]) 64 pos += 2 65 66 l := int(data[pos]) 67 result.Database = string(data[pos+1 : pos+1+l]) 68 pos += 1 + l + 1 69 70 l = int(data[pos]) 71 result.Name = string(data[pos+1 : pos+1+l]) 72 pos += 1 + l + 1 73 74 columnCount, read, ok := readLenEncInt(data, pos) 75 if !ok { 76 return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "expected column count at position %v (data=%v)", pos, data) 77 } 78 pos = read 79 80 result.Types = data[pos : pos+int(columnCount)] 81 pos += int(columnCount) 82 83 metaLen, read, ok := readLenEncInt(data, pos) 84 if !ok { 85 return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "expected metadata length at position %v (data=%v)", pos, data) 86 } 87 pos = read 88 89 // Allocate and parse / copy Metadata. 90 result.Metadata = make([]uint16, columnCount) 91 expectedEnd := pos + int(metaLen) 92 for c := uint64(0); c < columnCount; c++ { 93 var err error 94 result.Metadata[c], pos, err = metadataRead(data, pos, result.Types[c]) 95 if err != nil { 96 return nil, err 97 } 98 } 99 if pos != expectedEnd { 100 return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "unexpected metadata end: got %v was expecting %v (data=%v)", pos, expectedEnd, data) 101 } 102 103 // A bit array that says if each column can be NULL. 104 result.CanBeNull, _ = newBitmap(data, pos, int(columnCount)) 105 106 return result, nil 107 } 108 109 // metadataLength returns how many bytes are used for metadata, based on a type. 110 func metadataLength(typ byte) int { 111 switch typ { 112 case TypeDecimal, TypeTiny, TypeShort, TypeLong, TypeNull, TypeTimestamp, TypeLongLong, TypeInt24, TypeDate, TypeTime, TypeDateTime, TypeYear, TypeNewDate: 113 // No data here. 114 return 0 115 116 case TypeFloat, TypeDouble, TypeTimestamp2, TypeDateTime2, TypeTime2, TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry: 117 // One byte. 118 return 1 119 120 case TypeNewDecimal, TypeEnum, TypeSet, TypeString: 121 // Two bytes, Big Endian because of crazy encoding. 122 return 2 123 124 case TypeVarchar, TypeBit, TypeVarString: 125 // Two bytes, Little Endian 126 return 2 127 128 default: 129 // Unknown type. This is used in tests only, so panic. 130 panic(vterrors.Errorf(vtrpc.Code_INTERNAL, "metadataLength: unhandled data type: %v", typ)) 131 } 132 } 133 134 // metadataTotalLength returns the total size of the metadata for an 135 // array of types. 136 func metadataTotalLength(types []byte) int { 137 sum := 0 138 for _, t := range types { 139 sum += metadataLength(t) 140 } 141 return sum 142 } 143 144 // metadataRead reads a single value from the metadata string. 145 func metadataRead(data []byte, pos int, typ byte) (uint16, int, error) { 146 switch typ { 147 148 case TypeDecimal, TypeTiny, TypeShort, TypeLong, TypeNull, TypeTimestamp, TypeLongLong, TypeInt24, TypeDate, TypeTime, TypeDateTime, TypeYear, TypeNewDate: 149 // No data here. 150 return 0, pos, nil 151 152 case TypeFloat, TypeDouble, TypeTimestamp2, TypeDateTime2, TypeTime2, TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry: 153 // One byte. 154 return uint16(data[pos]), pos + 1, nil 155 156 case TypeNewDecimal, TypeEnum, TypeSet, TypeString: 157 // Two bytes, Big Endian because of crazy encoding. 158 return uint16(data[pos])<<8 + uint16(data[pos+1]), pos + 2, nil 159 160 case TypeVarchar, TypeBit, TypeVarString: 161 // Two bytes, Little Endian 162 return uint16(data[pos]) + uint16(data[pos+1])<<8, pos + 2, nil 163 164 default: 165 // Unknown types, we can't go on. 166 return 0, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "metadataRead: unhandled data type: %v", typ) 167 } 168 } 169 170 // metadataWrite writes a single value into the metadata string. 171 func metadataWrite(data []byte, pos int, typ byte, value uint16) int { 172 switch typ { 173 174 case TypeDecimal, TypeTiny, TypeShort, TypeLong, TypeNull, TypeTimestamp, TypeLongLong, TypeInt24, TypeDate, TypeTime, TypeDateTime, TypeYear, TypeNewDate: 175 // No data here. 176 return pos 177 178 case TypeFloat, TypeDouble, TypeTimestamp2, TypeDateTime2, TypeTime2, TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry: 179 // One byte. 180 data[pos] = byte(value) 181 return pos + 1 182 183 case TypeNewDecimal, TypeEnum, TypeSet, TypeString: 184 // Two bytes, Big Endian because of crazy encoding. 185 data[pos] = byte(value >> 8) 186 data[pos+1] = byte(value) 187 return pos + 2 188 189 case TypeVarchar, TypeBit, TypeVarString: 190 // Two bytes, Little Endian 191 data[pos] = byte(value) 192 data[pos+1] = byte(value >> 8) 193 return pos + 2 194 195 default: 196 // Unknown type. This is used in tests only, so panic. 197 panic(vterrors.Errorf(vtrpc.Code_INTERNAL, "metadataRead: unhandled data type: %v", typ)) 198 } 199 } 200 201 var dig2bytes = []int{0, 1, 1, 2, 2, 3, 3, 4, 4, 4} 202 203 // cellLength returns the new position after the field with the given 204 // type is read. 205 func cellLength(data []byte, pos int, typ byte, metadata uint16) (int, error) { 206 switch typ { 207 case TypeNull: 208 return 0, nil 209 case TypeTiny, TypeYear: 210 return 1, nil 211 case TypeShort: 212 return 2, nil 213 case TypeInt24: 214 return 3, nil 215 case TypeLong, TypeFloat, TypeTimestamp: 216 return 4, nil 217 case TypeLongLong, TypeDouble: 218 return 8, nil 219 case TypeDate, TypeTime, TypeNewDate: 220 return 3, nil 221 case TypeDateTime: 222 return 8, nil 223 case TypeVarchar, TypeVarString: 224 // Length is encoded in 1 or 2 bytes. 225 if metadata > 255 { 226 l := int(uint64(data[pos]) | 227 uint64(data[pos+1])<<8) 228 return l + 2, nil 229 } 230 l := int(data[pos]) 231 return l + 1, nil 232 case TypeBit: 233 // bitmap length is in metadata, as: 234 // upper 8 bits: bytes length 235 // lower 8 bits: bit length 236 nbits := ((metadata >> 8) * 8) + (metadata & 0xFF) 237 return (int(nbits) + 7) / 8, nil 238 case TypeTimestamp2: 239 // metadata has number of decimals. One byte encodes 240 // two decimals. 241 return 4 + (int(metadata)+1)/2, nil 242 case TypeDateTime2: 243 // metadata has number of decimals. One byte encodes 244 // two decimals. 245 return 5 + (int(metadata)+1)/2, nil 246 case TypeTime2: 247 // metadata has number of decimals. One byte encodes 248 // two decimals. 249 return 3 + (int(metadata)+1)/2, nil 250 case TypeNewDecimal: 251 precision := int(metadata >> 8) 252 scale := int(metadata & 0xff) 253 // Example: 254 // NNNNNNNNNNNN.MMMMMM 255 // 12 bytes 6 bytes 256 // precision is 18 257 // scale is 6 258 // storage is done by groups of 9 digits: 259 // - 32 bits are used to store groups of 9 digits. 260 // - any leftover digit is stored in: 261 // - 1 byte for 1 and 2 digits 262 // - 2 bytes for 3 and 4 digits 263 // - 3 bytes for 5 and 6 digits 264 // - 4 bytes for 7 and 8 digits (would also work for 9) 265 // both sides of the dot are stored separately. 266 // In this example, we'd have: 267 // - 2 bytes to store the first 3 full digits. 268 // - 4 bytes to store the next 9 full digits. 269 // - 3 bytes to store the 6 fractional digits. 270 intg := precision - scale 271 intg0 := intg / 9 272 frac0 := scale / 9 273 intg0x := intg - intg0*9 274 frac0x := scale - frac0*9 275 return intg0*4 + dig2bytes[intg0x] + frac0*4 + dig2bytes[frac0x], nil 276 case TypeEnum, TypeSet: 277 return int(metadata & 0xff), nil 278 case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob, TypeGeometry: 279 // Of the Blobs, only TypeBlob is used in binary logs, 280 // but supports others just in case. 281 switch metadata { 282 case 1: 283 return 1 + int(uint32(data[pos])), nil 284 case 2: 285 return 2 + int(uint32(data[pos])| 286 uint32(data[pos+1])<<8), nil 287 case 3: 288 return 3 + int(uint32(data[pos])| 289 uint32(data[pos+1])<<8| 290 uint32(data[pos+2])<<16), nil 291 case 4: 292 return 4 + int(uint32(data[pos])| 293 uint32(data[pos+1])<<8| 294 uint32(data[pos+2])<<16| 295 uint32(data[pos+3])<<24), nil 296 default: 297 return 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unsupported blob/geometry metadata value %v (data: %v pos: %v)", metadata, data, pos) 298 } 299 case TypeString: 300 // This may do String, Enum, and Set. The type is in 301 // metadata. If it's a string, then there will be more bits. 302 // This will give us the maximum length of the field. 303 t := metadata >> 8 304 if t == TypeEnum || t == TypeSet { 305 return int(metadata & 0xff), nil 306 } 307 max := int((((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0xff)) 308 // Length is encoded in 1 or 2 bytes. 309 if max > 255 { 310 l := int(uint64(data[pos]) | 311 uint64(data[pos+1])<<8) 312 return l + 2, nil 313 } 314 l := int(data[pos]) 315 return l + 1, nil 316 317 default: 318 return 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unsupported type %v (data: %v pos: %v)", typ, data, pos) 319 } 320 } 321 322 // printTimestamp is a helper method to append a timestamp into a bytes.Buffer, 323 // and return the Buffer. 324 func printTimestamp(v uint32) *bytes.Buffer { 325 if v == 0 { 326 return bytes.NewBuffer(ZeroTimestamp) 327 } 328 329 t := time.Unix(int64(v), 0).UTC() 330 year, month, day := t.Date() 331 hour, minute, second := t.Clock() 332 333 result := &bytes.Buffer{} 334 fmt.Fprintf(result, "%04d-%02d-%02d %02d:%02d:%02d", year, int(month), day, hour, minute, second) 335 return result 336 } 337 338 // CellValue returns the data for a cell as a sqltypes.Value, and how 339 // many bytes it takes. It uses source type in querypb.Type and vitess type 340 // byte to determine general shared aspects of types and the querypb.Field to 341 // determine other info specifically about its underlying column (SQL column 342 // type, column length, charset, etc) 343 func CellValue(data []byte, pos int, typ byte, metadata uint16, field *querypb.Field) (sqltypes.Value, int, error) { 344 switch typ { 345 case TypeTiny: 346 if sqltypes.IsSigned(field.Type) { 347 return sqltypes.MakeTrusted(querypb.Type_INT8, 348 strconv.AppendInt(nil, int64(int8(data[pos])), 10)), 1, nil 349 } 350 return sqltypes.MakeTrusted(querypb.Type_UINT8, 351 strconv.AppendUint(nil, uint64(data[pos]), 10)), 1, nil 352 case TypeYear: 353 val := data[pos] 354 if val == 0 { 355 return sqltypes.MakeTrusted(querypb.Type_YEAR, 356 []byte{'0', '0', '0', '0'}), 1, nil 357 } 358 return sqltypes.MakeTrusted(querypb.Type_YEAR, 359 strconv.AppendUint(nil, uint64(data[pos])+1900, 10)), 1, nil 360 case TypeShort: 361 val := binary.LittleEndian.Uint16(data[pos : pos+2]) 362 if sqltypes.IsSigned(field.Type) { 363 return sqltypes.MakeTrusted(querypb.Type_INT16, 364 strconv.AppendInt(nil, int64(int16(val)), 10)), 2, nil 365 } 366 return sqltypes.MakeTrusted(querypb.Type_UINT16, 367 strconv.AppendUint(nil, uint64(val), 10)), 2, nil 368 case TypeInt24: 369 if sqltypes.IsSigned(field.Type) && data[pos+2]&128 > 0 { 370 // Negative number, have to extend the sign. 371 val := int32(uint32(data[pos]) + 372 uint32(data[pos+1])<<8 + 373 uint32(data[pos+2])<<16 + 374 uint32(255)<<24) 375 return sqltypes.MakeTrusted(querypb.Type_INT24, 376 strconv.AppendInt(nil, int64(val), 10)), 3, nil 377 } 378 // Positive number. 379 val := uint64(data[pos]) + 380 uint64(data[pos+1])<<8 + 381 uint64(data[pos+2])<<16 382 return sqltypes.MakeTrusted(querypb.Type_UINT24, 383 strconv.AppendUint(nil, val, 10)), 3, nil 384 case TypeLong: 385 val := binary.LittleEndian.Uint32(data[pos : pos+4]) 386 if sqltypes.IsSigned(field.Type) { 387 return sqltypes.MakeTrusted(querypb.Type_INT32, 388 strconv.AppendInt(nil, int64(int32(val)), 10)), 4, nil 389 } 390 return sqltypes.MakeTrusted(querypb.Type_UINT32, 391 strconv.AppendUint(nil, uint64(val), 10)), 4, nil 392 case TypeFloat: 393 val := binary.LittleEndian.Uint32(data[pos : pos+4]) 394 fval := math.Float32frombits(val) 395 return sqltypes.MakeTrusted(querypb.Type_FLOAT32, 396 strconv.AppendFloat(nil, float64(fval), 'E', -1, 32)), 4, nil 397 case TypeDouble: 398 val := binary.LittleEndian.Uint64(data[pos : pos+8]) 399 fval := math.Float64frombits(val) 400 return sqltypes.MakeTrusted(querypb.Type_FLOAT64, 401 strconv.AppendFloat(nil, fval, 'E', -1, 64)), 8, nil 402 case TypeTimestamp: 403 val := binary.LittleEndian.Uint32(data[pos : pos+4]) 404 txt := printTimestamp(val) 405 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 406 txt.Bytes()), 4, nil 407 case TypeLongLong: 408 val := binary.LittleEndian.Uint64(data[pos : pos+8]) 409 if sqltypes.IsSigned(field.Type) { 410 return sqltypes.MakeTrusted(querypb.Type_INT64, 411 strconv.AppendInt(nil, int64(val), 10)), 8, nil 412 } 413 return sqltypes.MakeTrusted(querypb.Type_UINT64, 414 strconv.AppendUint(nil, val, 10)), 8, nil 415 case TypeDate, TypeNewDate: 416 val := uint32(data[pos]) + 417 uint32(data[pos+1])<<8 + 418 uint32(data[pos+2])<<16 419 day := val & 31 420 month := val >> 5 & 15 421 year := val >> 9 422 return sqltypes.MakeTrusted(querypb.Type_DATE, 423 []byte(fmt.Sprintf("%04d-%02d-%02d", year, month, day))), 3, nil 424 case TypeTime: 425 var hour, minute, second int32 426 if data[pos+2]&128 > 0 { 427 // Negative number, have to extend the sign. 428 val := int32(uint32(data[pos]) + 429 uint32(data[pos+1])<<8 + 430 uint32(data[pos+2])<<16 + 431 uint32(255)<<24) 432 hour = val / 10000 433 minute = -((val % 10000) / 100) 434 second = -(val % 100) 435 } else { 436 val := int32(data[pos]) + 437 int32(data[pos+1])<<8 + 438 int32(data[pos+2])<<16 439 hour = val / 10000 440 minute = (val % 10000) / 100 441 second = val % 100 442 } 443 return sqltypes.MakeTrusted(querypb.Type_TIME, 444 []byte(fmt.Sprintf("%02d:%02d:%02d", hour, minute, second))), 3, nil 445 case TypeDateTime: 446 val := binary.LittleEndian.Uint64(data[pos : pos+8]) 447 d := val / 1000000 448 t := val % 1000000 449 year := d / 10000 450 month := (d % 10000) / 100 451 day := d % 100 452 hour := t / 10000 453 minute := (t % 10000) / 100 454 second := t % 100 455 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 456 []byte(fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second))), 8, nil 457 case TypeVarchar, TypeVarString: 458 // We trust that typ is compatible with the field.Type 459 // Length is encoded in 1 or 2 bytes. 460 typeToUse := querypb.Type_VARCHAR 461 if field.Type == querypb.Type_VARBINARY || field.Type == querypb.Type_BINARY || field.Type == querypb.Type_BLOB { 462 typeToUse = field.Type 463 } 464 if metadata > 255 { 465 l := int(uint64(data[pos]) | 466 uint64(data[pos+1])<<8) 467 return sqltypes.MakeTrusted(typeToUse, 468 data[pos+2:pos+2+l]), l + 2, nil 469 } 470 l := int(data[pos]) 471 return sqltypes.MakeTrusted(typeToUse, 472 data[pos+1:pos+1+l]), l + 1, nil 473 case TypeBit: 474 // The contents is just the bytes, quoted. 475 nbits := ((metadata >> 8) * 8) + (metadata & 0xFF) 476 l := (int(nbits) + 7) / 8 477 return sqltypes.MakeTrusted(querypb.Type_BIT, 478 data[pos:pos+l]), l, nil 479 case TypeTimestamp2: 480 second := binary.BigEndian.Uint32(data[pos : pos+4]) 481 txt := printTimestamp(second) 482 switch metadata { 483 case 1: 484 decimals := int(data[pos+4]) 485 fmt.Fprintf(txt, ".%01d", decimals/10) 486 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 487 txt.Bytes()), 5, nil 488 case 2: 489 decimals := int(data[pos+4]) 490 fmt.Fprintf(txt, ".%02d", decimals) 491 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 492 txt.Bytes()), 5, nil 493 case 3: 494 decimals := int(data[pos+4])<<8 + 495 int(data[pos+5]) 496 fmt.Fprintf(txt, ".%03d", decimals/10) 497 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 498 txt.Bytes()), 6, nil 499 case 4: 500 decimals := int(data[pos+4])<<8 + 501 int(data[pos+5]) 502 fmt.Fprintf(txt, ".%04d", decimals) 503 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 504 txt.Bytes()), 6, nil 505 case 5: 506 decimals := int(data[pos+4])<<16 + 507 int(data[pos+5])<<8 + 508 int(data[pos+6]) 509 fmt.Fprintf(txt, ".%05d", decimals/10) 510 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 511 txt.Bytes()), 7, nil 512 case 6: 513 decimals := int(data[pos+4])<<16 + 514 int(data[pos+5])<<8 + 515 int(data[pos+6]) 516 fmt.Fprintf(txt, ".%06d", decimals) 517 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 518 txt.Bytes()), 7, nil 519 } 520 return sqltypes.MakeTrusted(querypb.Type_TIMESTAMP, 521 txt.Bytes()), 4, nil 522 case TypeDateTime2: 523 ymdhms := (uint64(data[pos])<<32 | 524 uint64(data[pos+1])<<24 | 525 uint64(data[pos+2])<<16 | 526 uint64(data[pos+3])<<8 | 527 uint64(data[pos+4])) - uint64(0x8000000000) 528 ymd := ymdhms >> 17 529 ym := ymd >> 5 530 hms := ymdhms % (1 << 17) 531 532 day := ymd % (1 << 5) 533 month := ym % 13 534 year := ym / 13 535 536 second := hms % (1 << 6) 537 minute := (hms >> 6) % (1 << 6) 538 hour := hms >> 12 539 540 txt := &bytes.Buffer{} 541 fmt.Fprintf(txt, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second) 542 543 switch metadata { 544 case 1: 545 decimals := int(data[pos+5]) 546 fmt.Fprintf(txt, ".%01d", decimals/10) 547 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 548 txt.Bytes()), 6, nil 549 case 2: 550 decimals := int(data[pos+5]) 551 fmt.Fprintf(txt, ".%02d", decimals) 552 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 553 txt.Bytes()), 6, nil 554 case 3: 555 decimals := int(data[pos+5])<<8 + 556 int(data[pos+6]) 557 fmt.Fprintf(txt, ".%03d", decimals/10) 558 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 559 txt.Bytes()), 7, nil 560 case 4: 561 decimals := int(data[pos+5])<<8 + 562 int(data[pos+6]) 563 fmt.Fprintf(txt, ".%04d", decimals) 564 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 565 txt.Bytes()), 7, nil 566 case 5: 567 decimals := int(data[pos+5])<<16 + 568 int(data[pos+6])<<8 + 569 int(data[pos+7]) 570 fmt.Fprintf(txt, ".%05d", decimals/10) 571 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 572 txt.Bytes()), 8, nil 573 case 6: 574 decimals := int(data[pos+5])<<16 + 575 int(data[pos+6])<<8 + 576 int(data[pos+7]) 577 fmt.Fprintf(txt, ".%06d", decimals) 578 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 579 txt.Bytes()), 8, nil 580 } 581 return sqltypes.MakeTrusted(querypb.Type_DATETIME, 582 txt.Bytes()), 5, nil 583 case TypeTime2: 584 hms := (int64(data[pos])<<16 | 585 int64(data[pos+1])<<8 | 586 int64(data[pos+2])) - 0x800000 587 sign := "" 588 if hms < 0 { 589 hms = -hms 590 sign = "-" 591 } 592 593 fracStr := "" 594 switch metadata { 595 case 1: 596 frac := int(data[pos+3]) 597 if sign == "-" && frac != 0 { 598 hms-- 599 frac = 0x100 - frac 600 } 601 fracStr = fmt.Sprintf(".%.1d", frac/10) 602 case 2: 603 frac := int(data[pos+3]) 604 if sign == "-" && frac != 0 { 605 hms-- 606 frac = 0x100 - frac 607 } 608 fracStr = fmt.Sprintf(".%.2d", frac) 609 case 3: 610 frac := int(data[pos+3])<<8 | 611 int(data[pos+4]) 612 if sign == "-" && frac != 0 { 613 hms-- 614 frac = 0x10000 - frac 615 } 616 fracStr = fmt.Sprintf(".%.3d", frac/10) 617 case 4: 618 frac := int(data[pos+3])<<8 | 619 int(data[pos+4]) 620 if sign == "-" && frac != 0 { 621 hms-- 622 frac = 0x10000 - frac 623 } 624 fracStr = fmt.Sprintf(".%.4d", frac) 625 case 5: 626 frac := int(data[pos+3])<<16 | 627 int(data[pos+4])<<8 | 628 int(data[pos+5]) 629 if sign == "-" && frac != 0 { 630 hms-- 631 frac = 0x1000000 - frac 632 } 633 fracStr = fmt.Sprintf(".%.5d", frac/10) 634 case 6: 635 frac := int(data[pos+3])<<16 | 636 int(data[pos+4])<<8 | 637 int(data[pos+5]) 638 if sign == "-" && frac != 0 { 639 hms-- 640 frac = 0x1000000 - frac 641 } 642 fracStr = fmt.Sprintf(".%.6d", frac) 643 } 644 645 hour := (hms >> 12) % (1 << 10) 646 minute := (hms >> 6) % (1 << 6) 647 second := hms % (1 << 6) 648 return sqltypes.MakeTrusted(querypb.Type_TIME, 649 []byte(fmt.Sprintf("%v%02d:%02d:%02d%v", sign, hour, minute, second, fracStr))), 3 + (int(metadata)+1)/2, nil 650 651 case TypeNewDecimal: 652 precision := int(metadata >> 8) // total digits number 653 scale := int(metadata & 0xff) // number of fractional digits 654 intg := precision - scale // number of full digits 655 intg0 := intg / 9 // number of 32-bits digits 656 intg0x := intg - intg0*9 // leftover full digits 657 frac0 := scale / 9 // number of 32 bits fractionals 658 frac0x := scale - frac0*9 // leftover fractionals 659 660 l := intg0*4 + dig2bytes[intg0x] + frac0*4 + dig2bytes[frac0x] 661 662 // Copy the data so we can change it. Otherwise 663 // decoding is just too hard. 664 d := make([]byte, l) 665 copy(d, data[pos:pos+l]) 666 667 txt := &bytes.Buffer{} 668 669 isNegative := (d[0] & 0x80) == 0 670 d[0] ^= 0x80 // First bit is inverted. 671 if isNegative { 672 // Negative numbers are just inverted bytes. 673 txt.WriteByte('-') 674 for i := range d { 675 d[i] ^= 0xff 676 } 677 } 678 679 // first we have the leftover full digits 680 var val uint32 681 switch dig2bytes[intg0x] { 682 case 0: 683 // nothing to do 684 case 1: 685 // one byte, up to two digits 686 val = uint32(d[0]) 687 case 2: 688 // two bytes, up to 4 digits 689 val = uint32(d[0])<<8 + 690 uint32(d[1]) 691 case 3: 692 // 3 bytes, up to 6 digits 693 val = uint32(d[0])<<16 + 694 uint32(d[1])<<8 + 695 uint32(d[2]) 696 case 4: 697 // 4 bytes, up to 8 digits (9 digits would be a full) 698 val = uint32(d[0])<<24 + 699 uint32(d[1])<<16 + 700 uint32(d[2])<<8 + 701 uint32(d[3]) 702 } 703 pos = dig2bytes[intg0x] 704 if val > 0 { 705 txt.Write(strconv.AppendUint(nil, uint64(val), 10)) 706 } 707 708 // now the full digits, 32 bits each, 9 digits 709 for i := 0; i < intg0; i++ { 710 val = binary.BigEndian.Uint32(d[pos : pos+4]) 711 fmt.Fprintf(txt, "%09d", val) 712 pos += 4 713 } 714 715 // now see if we have a fraction 716 if scale == 0 { 717 // When the field is a DECIMAL using a scale of 0, e.g. 718 // DECIMAL(5,0), a binlogged value of 0 is almost treated 719 // like the NULL byte and we get a 0 byte length value. 720 // In this case let's return the correct value of 0. 721 if txt.Len() == 0 { 722 txt.WriteRune('0') 723 } 724 725 return sqltypes.MakeTrusted(querypb.Type_DECIMAL, 726 txt.Bytes()), l, nil 727 } 728 txt.WriteByte('.') 729 730 // now the full fractional digits 731 for i := 0; i < frac0; i++ { 732 val = binary.BigEndian.Uint32(d[pos : pos+4]) 733 fmt.Fprintf(txt, "%09d", val) 734 pos += 4 735 } 736 737 // then the partial fractional digits 738 switch dig2bytes[frac0x] { 739 case 0: 740 // Nothing to do 741 return sqltypes.MakeTrusted(querypb.Type_DECIMAL, 742 txt.Bytes()), l, nil 743 case 1: 744 // one byte, 1 or 2 digits 745 val = uint32(d[pos]) 746 if frac0x == 1 { 747 fmt.Fprintf(txt, "%1d", val) 748 } else { 749 fmt.Fprintf(txt, "%02d", val) 750 } 751 case 2: 752 // two bytes, 3 or 4 digits 753 val = uint32(d[pos])<<8 + 754 uint32(d[pos+1]) 755 if frac0x == 3 { 756 fmt.Fprintf(txt, "%03d", val) 757 } else { 758 fmt.Fprintf(txt, "%04d", val) 759 } 760 case 3: 761 // 3 bytes, 5 or 6 digits 762 val = uint32(d[pos])<<16 + 763 uint32(d[pos+1])<<8 + 764 uint32(d[pos+2]) 765 if frac0x == 5 { 766 fmt.Fprintf(txt, "%05d", val) 767 } else { 768 fmt.Fprintf(txt, "%06d", val) 769 } 770 case 4: 771 // 4 bytes, 7 or 8 digits (9 digits would be a full) 772 val = uint32(d[pos])<<24 + 773 uint32(d[pos+1])<<16 + 774 uint32(d[pos+2])<<8 + 775 uint32(d[pos+3]) 776 if frac0x == 7 { 777 fmt.Fprintf(txt, "%07d", val) 778 } else { 779 fmt.Fprintf(txt, "%08d", val) 780 } 781 } 782 783 // remove preceding 0s from the integral part, otherwise we get "000000000001.23" instead of "1.23" 784 trimPrecedingZeroes := func(b []byte) []byte { 785 s := string(b) 786 isNegative := false 787 if s[0] == '-' { 788 isNegative = true 789 s = s[1:] 790 } 791 s = strings.TrimLeft(s, "0") 792 if isNegative { 793 s = fmt.Sprintf("-%s", s) 794 } 795 return []byte(s) 796 } 797 return sqltypes.MakeTrusted(querypb.Type_DECIMAL, trimPrecedingZeroes(txt.Bytes())), l, nil 798 799 case TypeEnum: 800 switch metadata & 0xff { 801 case 1: 802 // One byte storage. 803 return sqltypes.MakeTrusted(querypb.Type_ENUM, 804 strconv.AppendUint(nil, uint64(data[pos]), 10)), 1, nil 805 case 2: 806 // Two bytes storage. 807 val := binary.LittleEndian.Uint16(data[pos : pos+2]) 808 return sqltypes.MakeTrusted(querypb.Type_ENUM, 809 strconv.AppendUint(nil, uint64(val), 10)), 2, nil 810 default: 811 return sqltypes.NULL, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unexpected enum size: %v", metadata&0xff) 812 } 813 814 case TypeSet: 815 l := int(metadata & 0xff) 816 return sqltypes.MakeTrusted(querypb.Type_SET, 817 data[pos:pos+l]), l, nil 818 819 case TypeJSON, TypeTinyBlob, TypeMediumBlob, TypeLongBlob, TypeBlob: 820 // Only TypeBlob is used in binary logs, 821 // but supports others just in case. 822 l := 0 823 switch metadata { 824 case 1: 825 l = int(uint32(data[pos])) 826 case 2: 827 l = int(uint32(data[pos]) | 828 uint32(data[pos+1])<<8) 829 case 3: 830 l = int(uint32(data[pos]) | 831 uint32(data[pos+1])<<8 | 832 uint32(data[pos+2])<<16) 833 case 4: 834 l = int(uint32(data[pos]) | 835 uint32(data[pos+1])<<8 | 836 uint32(data[pos+2])<<16 | 837 uint32(data[pos+3])<<24) 838 default: 839 return sqltypes.NULL, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unsupported blob metadata value %v (data: %v pos: %v)", metadata, data, pos) 840 } 841 pos += int(metadata) 842 843 var limitArray = func(data []byte, limit int) []byte { 844 if len(data) > limit { 845 return data[:limit] 846 } 847 return data 848 } 849 // For JSON, we parse the data, and emit SQL. 850 if typ == TypeJSON { 851 var err error 852 jsonData := data[pos : pos+l] 853 s, err := getJSONValue(jsonData) 854 if err != nil { 855 return sqltypes.NULL, 0, vterrors.Wrapf(err, "error stringifying JSON data %v", limitArray(jsonData, 100)) 856 } 857 d := []byte(s) 858 return sqltypes.MakeTrusted(sqltypes.Expression, 859 d), l + int(metadata), nil 860 } 861 862 return sqltypes.MakeTrusted(querypb.Type_VARBINARY, 863 data[pos:pos+l]), l + int(metadata), nil 864 865 case TypeString: 866 // This may do String, Enum, and Set. The type is in 867 // metadata. If it's a string, then there will be more bits. 868 t := metadata >> 8 869 if t == TypeEnum { 870 // We don't know the string values. So just use the 871 // numbers. 872 switch metadata & 0xff { 873 case 1: 874 // One byte storage. 875 return sqltypes.MakeTrusted(querypb.Type_UINT8, 876 strconv.AppendUint(nil, uint64(data[pos]), 10)), 1, nil 877 case 2: 878 // Two bytes storage. 879 val := binary.LittleEndian.Uint16(data[pos : pos+2]) 880 return sqltypes.MakeTrusted(querypb.Type_UINT16, 881 strconv.AppendUint(nil, uint64(val), 10)), 2, nil 882 default: 883 return sqltypes.NULL, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unexpected enum size: %v", metadata&0xff) 884 } 885 } 886 if t == TypeSet { 887 // We don't know the set values. So just use the 888 // numbers. 889 l := int(metadata & 0xff) 890 var val uint64 891 for i := 0; i < l; i++ { 892 val += uint64(data[pos+i]) << (uint(i) * 8) 893 } 894 return sqltypes.MakeTrusted(querypb.Type_UINT64, 895 strconv.AppendUint(nil, uint64(val), 10)), l, nil 896 } 897 // This is a real string. The length is weird. 898 max := int((((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0xff)) 899 // Length is encoded in 1 or 2 bytes. 900 if max > 255 { 901 // This code path exists due to https://bugs.mysql.com/bug.php?id=37426. 902 // CHAR types need to allocate 3 bytes per char. So, the length for CHAR(255) 903 // cannot be represented in 1 byte. This also means that this rule does not 904 // apply to BINARY data. 905 l := int(uint64(data[pos]) | 906 uint64(data[pos+1])<<8) 907 return sqltypes.MakeTrusted(querypb.Type_VARCHAR, 908 data[pos+2:pos+2+l]), l + 2, nil 909 } 910 l := int(data[pos]) 911 mdata := data[pos+1 : pos+1+l] 912 if sqltypes.IsBinary(field.Type) { 913 // For binary(n) column types, mysql pads the data on the right with nulls. However the binlog event contains 914 // the data without this padding. This causes several issues: 915 // * if a binary(n) column is part of the sharding key, the keyspace_id() returned during the copy phase 916 // (where the value is the result of a mysql query) is different from the one during replication 917 // (where the value is the one from the binlogs) 918 // * mysql where clause comparisons do not do the right thing without padding 919 // So for fixed length BINARY columns we right-pad it with nulls if necessary to match what MySQL returns. 920 // Because CHAR columns with a binary collation (e.g. utf8mb4_bin) have the same metadata as a BINARY column 921 // in binlog events, we also need to check for this case based on the underlying column type. 922 if l < max && strings.HasPrefix(strings.ToLower(field.ColumnType), "binary") { 923 paddedData := make([]byte, max) 924 copy(paddedData[:l], mdata) 925 mdata = paddedData 926 } 927 return sqltypes.MakeTrusted(querypb.Type_BINARY, mdata), l + 1, nil 928 } 929 return sqltypes.MakeTrusted(querypb.Type_VARCHAR, mdata), l + 1, nil 930 931 case TypeGeometry: 932 l := 0 933 switch metadata { 934 case 1: 935 l = int(uint32(data[pos])) 936 case 2: 937 l = int(uint32(data[pos]) | 938 uint32(data[pos+1])<<8) 939 case 3: 940 l = int(uint32(data[pos]) | 941 uint32(data[pos+1])<<8 | 942 uint32(data[pos+2])<<16) 943 case 4: 944 l = int(uint32(data[pos]) | 945 uint32(data[pos+1])<<8 | 946 uint32(data[pos+2])<<16 | 947 uint32(data[pos+3])<<24) 948 default: 949 return sqltypes.NULL, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unsupported geometry metadata value %v (data: %v pos: %v)", metadata, data, pos) 950 } 951 pos += int(metadata) 952 return sqltypes.MakeTrusted(querypb.Type_GEOMETRY, 953 data[pos:pos+l]), l + int(metadata), nil 954 955 default: 956 return sqltypes.NULL, 0, vterrors.Errorf(vtrpc.Code_INTERNAL, "unsupported type %v", typ) 957 } 958 } 959 960 // Rows implements BinlogEvent.TableMap(). 961 // 962 // Expected format (L = total length of event data): 963 // 964 // # bytes field 965 // 4/6 table id 966 // 2 flags 967 // -- if version == 2 968 // 2 extra data length edl 969 // edl extra data 970 // -- endif 971 // 972 // <var> number of columns (var-len encoded) 973 // <var> identify bitmap 974 // <var> data bitmap 975 // -- for each row 976 // <var> null bitmap for identify for present rows 977 // <var> values for each identify field 978 // <var> null bitmap for data for present rows 979 // <var> values for each data field 980 // -- 981 func (ev binlogEvent) Rows(f BinlogFormat, tm *TableMap) (Rows, error) { 982 typ := ev.Type() 983 data := ev.Bytes()[f.HeaderLength:] 984 hasIdentify := typ == eUpdateRowsEventV1 || typ == eUpdateRowsEventV2 || 985 typ == eDeleteRowsEventV1 || typ == eDeleteRowsEventV2 986 hasData := typ == eWriteRowsEventV1 || typ == eWriteRowsEventV2 || 987 typ == eUpdateRowsEventV1 || typ == eUpdateRowsEventV2 988 989 result := Rows{} 990 pos := 6 991 if f.HeaderSize(typ) == 6 { 992 pos = 4 993 } 994 result.Flags = binary.LittleEndian.Uint16(data[pos : pos+2]) 995 pos += 2 996 997 // version=2 have extra data here. 998 if typ == eWriteRowsEventV2 || typ == eUpdateRowsEventV2 || typ == eDeleteRowsEventV2 { 999 // This extraDataLength contains the 2 bytes length. 1000 extraDataLength := binary.LittleEndian.Uint16(data[pos : pos+2]) 1001 pos += int(extraDataLength) 1002 } 1003 1004 columnCount, read, ok := readLenEncInt(data, pos) 1005 if !ok { 1006 return result, vterrors.Errorf(vtrpc.Code_INTERNAL, "expected column count at position %v (data=%v)", pos, data) 1007 } 1008 pos = read 1009 1010 numIdentifyColumns := 0 1011 numDataColumns := 0 1012 1013 if hasIdentify { 1014 // Bitmap of the columns used for identify. 1015 result.IdentifyColumns, pos = newBitmap(data, pos, int(columnCount)) 1016 numIdentifyColumns = result.IdentifyColumns.BitCount() 1017 } 1018 1019 if hasData { 1020 // Bitmap of columns that are present. 1021 result.DataColumns, pos = newBitmap(data, pos, int(columnCount)) 1022 numDataColumns = result.DataColumns.BitCount() 1023 } 1024 1025 // One row at a time. 1026 for pos < len(data) { 1027 row := Row{} 1028 1029 if hasIdentify { 1030 // Bitmap of identify columns that are null (amongst the ones that are present). 1031 row.NullIdentifyColumns, pos = newBitmap(data, pos, numIdentifyColumns) 1032 1033 // Get the identify values. 1034 startPos := pos 1035 valueIndex := 0 1036 for c := 0; c < int(columnCount); c++ { 1037 if !result.IdentifyColumns.Bit(c) { 1038 // This column is not represented. 1039 continue 1040 } 1041 1042 if row.NullIdentifyColumns.Bit(valueIndex) { 1043 // This column is represented, but its value is NULL. 1044 valueIndex++ 1045 continue 1046 } 1047 1048 // This column is represented now. We need to skip its length. 1049 l, err := cellLength(data, pos, tm.Types[c], tm.Metadata[c]) 1050 if err != nil { 1051 return result, err 1052 } 1053 pos += l 1054 valueIndex++ 1055 } 1056 row.Identify = data[startPos:pos] 1057 } 1058 1059 if hasData { 1060 // Bitmap of columns that are null (amongst the ones that are present). 1061 row.NullColumns, pos = newBitmap(data, pos, numDataColumns) 1062 1063 // Get the values. 1064 startPos := pos 1065 valueIndex := 0 1066 for c := 0; c < int(columnCount); c++ { 1067 if !result.DataColumns.Bit(c) { 1068 // This column is not represented. 1069 continue 1070 } 1071 1072 if row.NullColumns.Bit(valueIndex) { 1073 // This column is represented, but its value is NULL. 1074 valueIndex++ 1075 continue 1076 } 1077 1078 // This column is represented now. We need to skip its length. 1079 l, err := cellLength(data, pos, tm.Types[c], tm.Metadata[c]) 1080 if err != nil { 1081 return result, err 1082 } 1083 pos += l 1084 valueIndex++ 1085 } 1086 row.Data = data[startPos:pos] 1087 } 1088 1089 result.Rows = append(result.Rows, row) 1090 } 1091 1092 return result, nil 1093 } 1094 1095 // StringValuesForTests is a helper method to return the string value 1096 // of all columns in a row in a Row. Only use it in tests, as the 1097 // returned values cannot be interpreted correctly without the schema. 1098 // We assume everything is unsigned in this method. 1099 func (rs *Rows) StringValuesForTests(tm *TableMap, rowIndex int) ([]string, error) { 1100 var result []string 1101 1102 valueIndex := 0 1103 data := rs.Rows[rowIndex].Data 1104 pos := 0 1105 for c := 0; c < rs.DataColumns.Count(); c++ { 1106 if !rs.DataColumns.Bit(c) { 1107 continue 1108 } 1109 1110 if rs.Rows[rowIndex].NullColumns.Bit(valueIndex) { 1111 // This column is represented, but its value is NULL. 1112 result = append(result, "NULL") 1113 valueIndex++ 1114 continue 1115 } 1116 1117 // We have real data 1118 value, l, err := CellValue(data, pos, tm.Types[c], tm.Metadata[c], &querypb.Field{Type: querypb.Type_UINT64}) 1119 if err != nil { 1120 return nil, err 1121 } 1122 result = append(result, value.ToString()) 1123 pos += l 1124 valueIndex++ 1125 } 1126 1127 return result, nil 1128 } 1129 1130 // StringIdentifiesForTests is a helper method to return the string 1131 // identify of all columns in a row in a Row. Only use it in tests, as the 1132 // returned values cannot be interpreted correctly without the schema. 1133 // We assume everything is unsigned in this method. 1134 func (rs *Rows) StringIdentifiesForTests(tm *TableMap, rowIndex int) ([]string, error) { 1135 var result []string 1136 1137 valueIndex := 0 1138 data := rs.Rows[rowIndex].Identify 1139 pos := 0 1140 for c := 0; c < rs.IdentifyColumns.Count(); c++ { 1141 if !rs.IdentifyColumns.Bit(c) { 1142 continue 1143 } 1144 1145 if rs.Rows[rowIndex].NullIdentifyColumns.Bit(valueIndex) { 1146 // This column is represented, but its value is NULL. 1147 result = append(result, "NULL") 1148 valueIndex++ 1149 continue 1150 } 1151 1152 // We have real data 1153 value, l, err := CellValue(data, pos, tm.Types[c], tm.Metadata[c], &querypb.Field{Type: querypb.Type_UINT64}) 1154 if err != nil { 1155 return nil, err 1156 } 1157 result = append(result, value.ToString()) 1158 pos += l 1159 valueIndex++ 1160 } 1161 1162 return result, nil 1163 }