@@ -2,6 +2,8 @@ package mysql
22
33import (
44"fmt"
5+ "strconv"
6+ "strings"
57)
68
79// For binlog filename + position based replication
@@ -12,22 +14,67 @@ type Position struct {
1214
1315func (p Position ) Compare (o Position ) int {
1416// First compare binlog name
15- if p .Name > o .Name {
17+ nameCmp := CompareBinlogFileName (p .Name , o .Name )
18+ if nameCmp != 0 {
19+ return nameCmp
20+ }
21+ // Same binlog file, compare position
22+ if p .Pos > o .Pos {
1623return 1
17- } else if p .Name < o .Name {
24+ } else if p .Pos < o .Pos {
1825return - 1
1926} else {
20- // Same binlog file, compare position
21- if p .Pos > o .Pos {
22- return 1
23- } else if p .Pos < o .Pos {
24- return - 1
25- } else {
26- return 0
27- }
27+ return 0
2828}
2929}
3030
3131func (p Position ) String () string {
3232return fmt .Sprintf ("(%s, %d)" , p .Name , p .Pos )
3333}
34+
35+ func CompareBinlogFileName (a , b string ) int {
36+ // sometimes it's convenient to construct a `Position` literal with no `Name`
37+ if a == "" && b == "" {
38+ return 0
39+ } else if a == "" {
40+ return - 1
41+ } else if b == "" {
42+ return 1
43+ }
44+
45+ splitBinlogName := func (n string ) (string , int ) {
46+ // mysqld appends a numeric extension to the binary log base name to generate binary log file names
47+ // ...
48+ // If you supply an extension in the log name (for example, --log-bin=base_name.extension),
49+ // the extension is silently removed and ignored.
50+ // ref: https://dev.mysql.com/doc/refman/8.0/en/binary-log.html
51+ i := strings .LastIndexByte (n , '.' )
52+ if i == - 1 {
53+ // try keeping backward compatibility
54+ return n , 0
55+ }
56+
57+ seq , err := strconv .Atoi (n [i + 1 :])
58+ if err != nil {
59+ panic (fmt .Sprintf ("binlog file %s doesn't contain numeric extension" , err ))
60+ }
61+ return n [:i ], seq
62+ }
63+
64+ aBase , aSeq := splitBinlogName (a )
65+ bBase , bSeq := splitBinlogName (b )
66+
67+ if aBase > bBase {
68+ return 1
69+ } else if aBase < bBase {
70+ return - 1
71+ }
72+
73+ if aSeq > bSeq {
74+ return 1
75+ } else if aSeq < bSeq {
76+ return - 1
77+ } else {
78+ return 0
79+ }
80+ }
0 commit comments