Skip to content

Commit 5ad36fa

Browse files
dveedenlance6716
andauthored
dump: use --source-data based on version (#933)
* dump: use --source-data based on version * Fix issue found by linter --------- Co-authored-by: lance6716 <[email protected]>
1 parent 03f4d7c commit 5ad36fa

File tree

2 files changed

+118
-6
lines changed

2 files changed

+118
-6
lines changed

dump/dumper.go

+56-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"os"
88
"os/exec"
9+
"regexp"
910
"strings"
1011

1112
. "github.com/go-mysql-org/go-mysql/mysql"
@@ -44,6 +45,9 @@ type Dumper struct {
4445

4546
// see detectColumnStatisticsParamSupported
4647
isColumnStatisticsParamSupported bool
48+
49+
mysqldumpVersion string
50+
sourceDataSupported bool
4751
}
4852

4953
func NewDumper(executionPath string, addr string, user string, password string) (*Dumper, error) {
@@ -67,7 +71,14 @@ func NewDumper(executionPath string, addr string, user string, password string)
6771
d.IgnoreTables = make(map[string][]string)
6872
d.ExtraOptions = make([]string, 0, 5)
6973
d.masterDataSkipped = false
70-
d.isColumnStatisticsParamSupported = d.detectColumnStatisticsParamSupported()
74+
75+
out, err := exec.Command(d.ExecutionPath, `--help`).CombinedOutput()
76+
if err != nil {
77+
return d, err
78+
}
79+
d.isColumnStatisticsParamSupported = d.detectColumnStatisticsParamSupported(out)
80+
d.mysqldumpVersion = d.getMysqldumpVersion(out)
81+
d.sourceDataSupported = d.detectSourceDataSupported(d.mysqldumpVersion)
7182

7283
d.ErrOut = os.Stderr
7384

@@ -81,12 +92,47 @@ func NewDumper(executionPath string, addr string, user string, password string)
8192
// But this parameter exists only for versions >=8.0.2 (https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-2.html).
8293
//
8394
// For environments where the version of mysql-server and mysqldump differs, we try to check this parameter and use it if available.
84-
func (d *Dumper) detectColumnStatisticsParamSupported() bool {
85-
out, err := exec.Command(d.ExecutionPath, `--help`).CombinedOutput()
86-
if err != nil {
95+
func (d *Dumper) detectColumnStatisticsParamSupported(helpOutput []byte) bool {
96+
return bytes.Contains(helpOutput, []byte(`--column-statistics`))
97+
}
98+
99+
// mysqldump Ver 10.19 Distrib 10.3.37-MariaDB, for linux-systemd (x86_64)`, `10.3.37-MariaDB
100+
// opt/mysql/11.0.0/bin/mysqldump from 11.0.0-preview-MariaDB, client 10.19 for linux-systemd (x86_64)
101+
func (d *Dumper) getMysqldumpVersion(helpOutput []byte) string {
102+
mysqldumpVersionRegexpNew := regexp.MustCompile(`mysqldump Ver ([0-9][^ ]*) for`)
103+
if m := mysqldumpVersionRegexpNew.FindSubmatch(helpOutput); m != nil {
104+
return string(m[1])
105+
}
106+
107+
mysqldumpVersionRegexpOld := regexp.MustCompile(`mysqldump Ver .* Distrib ([0-9][^ ]*),`)
108+
if m := mysqldumpVersionRegexpOld.FindSubmatch(helpOutput); m != nil {
109+
return string(m[1])
110+
}
111+
112+
mysqldumpVersionRegexpMaria := regexp.MustCompile(`mysqldump from ([0-9][^ ]*), `)
113+
if m := mysqldumpVersionRegexpMaria.FindSubmatch(helpOutput); m != nil {
114+
return string(m[1])
115+
}
116+
117+
return ""
118+
}
119+
120+
func (d *Dumper) detectSourceDataSupported(version string) bool {
121+
// Failed to detect mysqldump version
122+
if version == "" {
123+
return false
124+
}
125+
126+
// MySQL 5.x
127+
if version[0] == byte('5') {
128+
return false
129+
}
130+
131+
if strings.Contains(version, "MariaDB") {
87132
return false
88133
}
89-
return bytes.Contains(out, []byte(`--column-statistics`))
134+
135+
return true
90136
}
91137

92138
func (d *Dumper) SetCharset(charset string) {
@@ -169,7 +215,11 @@ func (d *Dumper) Dump(w io.Writer) error {
169215
passwordArgIndex := len(args) - 1
170216

171217
if !d.masterDataSkipped {
172-
args = append(args, "--master-data")
218+
if d.sourceDataSupported {
219+
args = append(args, "--source-data")
220+
} else {
221+
args = append(args, "--master-data")
222+
}
173223
}
174224

175225
if d.maxAllowedPacket > 0 {

dump/dumper_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package dump
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestGetMysqldumpVersion(t *testing.T) {
10+
versions := []struct {
11+
line string // mysqldump --help | head -1
12+
version string // 9.1.0
13+
}{
14+
// Oracle MySQL
15+
{`mysqldump Ver 10.13 Distrib 5.5.62, for linux-glibc2.12 (x86_64)`, `5.5.62`},
16+
{`mysqldump Ver 10.13 Distrib 5.6.44, for linux-glibc2.12 (x86_64)`, `5.6.44`},
17+
{`mysqldump Ver 10.13 Distrib 5.7.31, for linux-glibc2.12 (x86_64)`, `5.7.31`},
18+
{`mysqldump Ver 10.13 Distrib 5.7.36, for linux-glibc2.12 (x86_64)`, `5.7.36`},
19+
{`mysqldump Ver 8.0.11 for linux-glibc2.12 on x86_64 (MySQL Community Server - GPL)`, `8.0.11`},
20+
{`mysqldump Ver 8.0.22 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.22`},
21+
{`mysqldump Ver 8.0.25 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.25`},
22+
{`mysqldump Ver 8.0.26 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.26`},
23+
{`mysqldump Ver 8.0.27 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.27`},
24+
{`mysqldump Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.28`},
25+
{`mysqldump Ver 8.0.31 for Linux on x86_64 (Source distribution)`, `8.0.31`},
26+
{`mysqldump Ver 8.0.32 for Linux on x86_64 (MySQL Community Server - GPL)`, `8.0.32`},
27+
{`mysqldump Ver 8.4.2 for FreeBSD14.0 on amd64 (Source distribution)`, `8.4.2`},
28+
{`mysqldump Ver 9.1.0 for Linux on x86_64 (MySQL Community Server - GPL)`, `9.1.0`},
29+
30+
// MariaDB
31+
{`mysqldump Ver 10.19 Distrib 10.3.37-MariaDB, for linux-systemd (x86_64)`, `10.3.37-MariaDB`},
32+
{`mysqldump Ver 10.19 Distrib 10.6.11-MariaDB, for linux-systemd (x86_64)`, `10.6.11-MariaDB`},
33+
{`opt/mysql/11.0.0/bin/mysqldump from 11.0.0-preview-MariaDB, client 10.19 for linux-systemd (x86_64)`, `11.0.0-preview-MariaDB`},
34+
{`opt/mysql/11.2.2/bin/mysqldump from 11.2.2-MariaDB, client 10.19 for linux-systemd (x86_64)`, `11.2.2-MariaDB`},
35+
}
36+
37+
d := new(Dumper)
38+
for _, v := range versions {
39+
ver := d.getMysqldumpVersion([]byte(v.line))
40+
require.Equal(t, v.version, ver, v.line)
41+
}
42+
}
43+
44+
func TestDetectSourceDataSupported(t *testing.T) {
45+
versions := []struct {
46+
version string
47+
supported bool
48+
}{
49+
{`5.7.40`, false},
50+
{`8.0.11`, true},
51+
{`8.4.1`, true},
52+
{`9.1.0`, true},
53+
{``, false},
54+
{`10.3.37-MariaDB`, false},
55+
{`11.2.2-MariaDB`, false},
56+
}
57+
58+
d := new(Dumper)
59+
for _, v := range versions {
60+
require.Equal(t, v.supported, d.detectSourceDataSupported(v.version), v.version)
61+
}
62+
}

0 commit comments

Comments
 (0)