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  }