github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/gtid/gtid.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 package gtid 15 16 import ( 17 "strings" 18 19 "github.com/go-mysql-org/go-mysql/mysql" 20 "github.com/pingcap/tiflow/dm/pkg/terror" 21 ) 22 23 var ( 24 emptyMySQLGTIDSet, _ = mysql.ParseMysqlGTIDSet("") 25 emptyMariaDBGTIDSet, _ = mysql.ParseMariadbGTIDSet("") 26 ) 27 28 // CheckGTIDSetEmpty is used to check whether a GTID set is zero. 29 func CheckGTIDSetEmpty(gSet mysql.GTIDSet) bool { 30 return gSet == nil || gSet.Equal(emptyMySQLGTIDSet) || gSet.Equal(emptyMariaDBGTIDSet) 31 } 32 33 // ParserGTID parses GTID from string. If the flavor is not specified, it will 34 // try mysql GTID first and then MariaDB GTID. 35 func ParserGTID(flavor, gtidStr string) (mysql.GTIDSet, error) { 36 var ( 37 err error 38 gtid mysql.GTIDSet 39 ) 40 41 if len(flavor) == 0 && len(gtidStr) == 0 { 42 // regard as mysql, mariadb always enabled gtid 43 return mysql.ParseGTIDSet(mysql.MySQLFlavor, "") 44 } 45 46 fla := flavor 47 switch fla { 48 case mysql.MySQLFlavor: 49 if IsZeroMySQLGTIDSet(gtidStr) { 50 gtid, err = mysql.ParseGTIDSet(fla, "") 51 } else { 52 gtid, err = mysql.ParseGTIDSet(fla, gtidStr) 53 } 54 case mysql.MariaDBFlavor: 55 if IsZeroMariaDBGTIDSet(gtidStr) { 56 gtid, err = mysql.ParseGTIDSet(fla, "") 57 } else { 58 gtid, err = mysql.ParseGTIDSet(fla, gtidStr) 59 } 60 case "": 61 fla = mysql.MySQLFlavor 62 gtid, err = mysql.ParseGTIDSet(fla, gtidStr) 63 if err != nil { 64 fla = mysql.MariaDBFlavor 65 gtid, err = mysql.ParseGTIDSet(fla, gtidStr) 66 } 67 default: 68 err = terror.ErrNotSupportedFlavor.Generate(flavor) 69 } 70 71 return gtid, err 72 } 73 74 // ZeroGTIDSet returns an empty GTID set. The flavor must be specified. 75 func ZeroGTIDSet(flavor string) (mysql.GTIDSet, error) { 76 return ParserGTID(flavor, "") 77 } 78 79 // MustZeroGTIDSet is used when you can make sure the flavor is valid. 80 func MustZeroGTIDSet(flavor string) mysql.GTIDSet { 81 gtid, err := ZeroGTIDSet(flavor) 82 if err != nil { 83 panic(err) 84 } 85 return gtid 86 } 87 88 // IsZeroMySQLGTIDSet is used to meet this usage: when user wants to start binlog 89 // replication from scratch, a "uuid:0" (MySQL flavor) or "0-0-0" (mariaDB) GTID 90 // set must be written, in order to distinguish that user forgets to write it. 91 func IsZeroMySQLGTIDSet(gStr string) bool { 92 sp := strings.Split(gStr, ",") 93 if len(sp) != 1 { 94 return false 95 } 96 97 sep := strings.Split(sp[0], ":") 98 if len(sep) != 2 { 99 return false 100 } 101 interval := strings.TrimSpace(sep[1]) 102 return interval == "0" 103 } 104 105 // IsZeroMariaDBGTIDSet is used to meet this usage: when user wants to start binlog 106 // replication from scratch, a "uuid:0" (MySQL flavor) or "0-0-0" (mariaDB) GTID 107 // set must be written, in order to distinguish that user forgets to write it. 108 // 109 // For MariaDB, the GTID set like "0-0-0" will confuse IsZeroGTIDSet function, 110 // so we also need to check the interval part. 111 func IsZeroMariaDBGTIDSet(gStr string) bool { 112 sp := strings.Split(gStr, ",") 113 if len(sp) != 1 { 114 return false 115 } 116 117 sep := strings.Split(sp[0], "-") 118 if len(sep) != 3 { 119 return false 120 } 121 interval := strings.TrimSpace(sep[2]) 122 return interval == "0" 123 }