vitess.io/vitess@v0.16.2/go/mysql/mysql56_gtid.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 "encoding/hex" 21 "fmt" 22 "strconv" 23 "strings" 24 25 "vitess.io/vitess/go/vt/proto/vtrpc" 26 "vitess.io/vitess/go/vt/vterrors" 27 ) 28 29 // Mysql56FlavorID is the string identifier for the Mysql56 flavor. 30 const Mysql56FlavorID = "MySQL56" 31 32 // parseMysql56GTID is registered as a GTID parser. 33 func parseMysql56GTID(s string) (GTID, error) { 34 // Split into parts. 35 parts := strings.Split(s, ":") 36 if len(parts) != 2 { 37 return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "invalid MySQL 5.6 GTID (%v): expecting UUID:Sequence", s) 38 } 39 40 // Parse Server ID. 41 sid, err := ParseSID(parts[0]) 42 if err != nil { 43 return nil, vterrors.Wrapf(err, "invalid MySQL 5.6 GTID Server ID (%v)", parts[0]) 44 } 45 46 // Parse Sequence number. 47 seq, err := strconv.ParseInt(parts[1], 10, 64) 48 if err != nil { 49 return nil, vterrors.Wrapf(err, "invalid MySQL 5.6 GTID Sequence number (%v)", parts[1]) 50 } 51 52 return Mysql56GTID{Server: sid, Sequence: seq}, nil 53 } 54 55 // SID is the 16-byte unique ID of a MySQL 5.6 server. 56 type SID [16]byte 57 58 // String prints an SID in the form used by MySQL 5.6. 59 func (sid SID) String() string { 60 dst := []byte("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") 61 hex.Encode(dst, sid[:4]) 62 hex.Encode(dst[9:], sid[4:6]) 63 hex.Encode(dst[14:], sid[6:8]) 64 hex.Encode(dst[19:], sid[8:10]) 65 hex.Encode(dst[24:], sid[10:16]) 66 return string(dst) 67 } 68 69 // ParseSID parses an SID in the form used by MySQL 5.6. 70 func ParseSID(s string) (sid SID, err error) { 71 if len(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { 72 return sid, vterrors.Errorf(vtrpc.Code_INTERNAL, "invalid MySQL 5.6 SID %q", s) 73 } 74 75 // Drop the dashes so we can just check the error of Decode once. 76 var b [32]byte 77 copy(b[0:], s[:8]) 78 copy(b[8:], s[9:13]) 79 copy(b[12:], s[14:18]) 80 copy(b[16:], s[19:23]) 81 copy(b[20:], s[24:]) 82 83 if _, err := hex.Decode(sid[:], b[:]); err != nil { 84 return sid, vterrors.Wrapf(err, "invalid MySQL 5.6 SID %q", s) 85 } 86 return sid, nil 87 } 88 89 // Mysql56GTID implements GTID 90 type Mysql56GTID struct { 91 // Server is the SID of the server that originally committed the transaction. 92 Server SID 93 // Sequence is the sequence number of the transaction within a given Server's 94 // scope. 95 Sequence int64 96 } 97 98 // String implements GTID.String(). 99 func (gtid Mysql56GTID) String() string { 100 return fmt.Sprintf("%s:%d", gtid.Server, gtid.Sequence) 101 } 102 103 // Flavor implements GTID.Flavor(). 104 func (gtid Mysql56GTID) Flavor() string { 105 return Mysql56FlavorID 106 } 107 108 // SequenceDomain implements GTID.SequenceDomain(). 109 func (gtid Mysql56GTID) SequenceDomain() any { 110 return nil 111 } 112 113 // SourceServer implements GTID.SourceServer(). 114 func (gtid Mysql56GTID) SourceServer() any { 115 return gtid.Server 116 } 117 118 // SequenceNumber implements GTID.SequenceNumber(). 119 func (gtid Mysql56GTID) SequenceNumber() any { 120 return gtid.Sequence 121 } 122 123 // GTIDSet implements GTID.GTIDSet(). 124 func (gtid Mysql56GTID) GTIDSet() GTIDSet { 125 return Mysql56GTIDSet{}.AddGTID(gtid) 126 } 127 128 func init() { 129 gtidParsers[Mysql56FlavorID] = parseMysql56GTID 130 }