vitess.io/vitess@v0.16.2/go/mysql/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 "fmt" 21 "strings" 22 23 "vitess.io/vitess/go/vt/proto/vtrpc" 24 "vitess.io/vitess/go/vt/vterrors" 25 ) 26 27 // GTID represents a Global Transaction ID, also known as Transaction Group ID. 28 // Each flavor of MySQL has its own format for the GTID. This interface is used 29 // along with various MysqlFlavor implementations to abstract the differences. 30 // 31 // Types that implement GTID should use a non-pointer receiver. This ensures 32 // that comparing GTID interface values with == has the expected semantics. 33 type GTID interface { 34 // String returns the canonical printed form of the GTID as expected by a 35 // particular flavor of MySQL. 36 String() string 37 38 // Flavor returns the key under which the corresponding GTID parser function 39 // is registered in the gtidParsers map. 40 Flavor() string 41 42 // SourceServer returns the ID of the server that generated the transaction. 43 SourceServer() any 44 45 // SequenceNumber returns the ID number that increases with each transaction. 46 // It is only valid to compare the sequence numbers of two GTIDs if they have 47 // the same domain value. 48 SequenceNumber() any 49 50 // SequenceDomain returns the ID of the domain within which two sequence 51 // numbers can be meaningfully compared. 52 SequenceDomain() any 53 54 // GTIDSet returns a GTIDSet of the same flavor as this GTID, containing only 55 // this GTID. 56 GTIDSet() GTIDSet 57 } 58 59 // gtidParsers maps flavor names to parser functions. 60 var gtidParsers = make(map[string]func(string) (GTID, error)) 61 62 // ParseGTID calls the GTID parser for the specified flavor. 63 func ParseGTID(flavor, value string) (GTID, error) { 64 parser := gtidParsers[flavor] 65 if parser == nil { 66 return nil, vterrors.Errorf(vtrpc.Code_INTERNAL, "parse error: unknown GTID flavor %#v", flavor) 67 } 68 return parser(value) 69 } 70 71 // MustParseGTID calls ParseGTID and panics on error. 72 func MustParseGTID(flavor, value string) GTID { 73 gtid, err := ParseGTID(flavor, value) 74 if err != nil { 75 panic(err) 76 } 77 return gtid 78 } 79 80 // EncodeGTID returns a string that contains both the flavor and value of the 81 // GTID, so that the correct parser can be selected when that string is passed 82 // to DecodeGTID. 83 func EncodeGTID(gtid GTID) string { 84 if gtid == nil { 85 return "" 86 } 87 88 return fmt.Sprintf("%s/%s", gtid.Flavor(), gtid.String()) 89 } 90 91 // DecodeGTID converts a string in the format returned by EncodeGTID back into 92 // a GTID interface value with the correct underlying flavor. 93 func DecodeGTID(s string) (GTID, error) { 94 if s == "" { 95 return nil, nil 96 } 97 98 parts := strings.SplitN(s, "/", 2) 99 if len(parts) != 2 { 100 // There is no flavor. Try looking for a default parser. 101 return ParseGTID("", s) 102 } 103 return ParseGTID(parts[0], parts[1]) 104 } 105 106 // MustDecodeGTID calls DecodeGTID and panics on error. 107 func MustDecodeGTID(s string) GTID { 108 gtid, err := DecodeGTID(s) 109 if err != nil { 110 panic(err) 111 } 112 return gtid 113 }