Skip to content

Commit 1f39a41

Browse files
authored
Merge branch 'master' into UUID-clone
2 parents c52248e + 0bd942a commit 1f39a41

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1701
-1230
lines changed

.github/workflows/ci.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: runTestsAndLinters
2+
on: [push, pull_request]
3+
4+
jobs:
5+
test:
6+
strategy:
7+
matrix:
8+
go: [ 1.16, 1.15 ]
9+
name: Tests Go ${{ matrix.go }}
10+
runs-on: ubuntu-18.04
11+
12+
steps:
13+
- name: Setup MySQL
14+
run: |
15+
echo -n "mysql -V: " ; mysql -V
16+
echo -n "mysqldump -V: " ; mysqldump -V
17+
18+
echo -e '[mysqld]\nserver-id=1\nlog-bin=mysql\nbinlog-format=row\ngtid-mode=ON\nenforce_gtid_consistency=ON\n' | sudo tee /etc/mysql/conf.d/replication.cnf
19+
sudo service mysql start
20+
sudo mysql -h 127.0.0.1 -uroot -proot -e "use mysql; update user set authentication_string=PASSWORD('') where User='root'; update user set plugin='mysql_native_password'; FLUSH PRIVILEGES;"
21+
# create ssl/rsa files for mysql ssl support
22+
sudo mysql_ssl_rsa_setup --uid=mysql
23+
mysql -e "CREATE DATABASE IF NOT EXISTS test;" -uroot
24+
mysql -e "SHOW VARIABLES LIKE 'log_bin'" -uroot
25+
- name: Prepare for Go
26+
run: |
27+
sudo apt-get install -y make gcc
28+
- name: Install Go
29+
uses: actions/setup-go@v2
30+
with:
31+
go-version: ${{ matrix.go }}
32+
- name: Checkout code
33+
uses: actions/checkout@v1
34+
- name: Run tests
35+
run: go test ./...
36+
37+
golangci:
38+
name: golangci
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v2
42+
- name: golangci-lint
43+
uses: golangci/golangci-lint-action@v2
44+
with:
45+
version: latest

.golangci.yml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
linters:
2+
disable-all: true
3+
enable:
4+
# All code is ready for:
5+
- deadcode
6+
- errcheck
7+
- staticcheck
8+
- structcheck
9+
- typecheck
10+
- unused
11+
- varcheck
12+
- misspell
13+
- nolintlint
14+
- goimports
15+
- nakedret
16+
- unconvert
17+
- whitespace
18+
# ToDo:
19+
#- gosimple
20+
#- govet
21+
#- ineffassign
22+
#- gocritic
23+
#- golint
24+
linters-settings:
25+
nolintlint:
26+
allow-unused: false
27+
allow-leading-space: false
28+
require-specific: true

.travis.yml

-47
This file was deleted.

CHANGELOG.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
### Tag v1.1.1 (2021.04.08)
2+
* Restructured dump/ tests. [#563](https://github.com/go-mysql-org/go-mysql/pull/563) ([atercattus](https://github.com/atercattus))
3+
* Replace magic numbers in canal/canal_test.go by constants. [#562](https://github.com/go-mysql-org/go-mysql/pull/562) ([atercattus](https://github.com/atercattus))
4+
* Fix parsing GTIDs from mysqlpdump. [#561](https://github.com/go-mysql-org/go-mysql/pull/561) ([dobegor](https://github.com/dobegor))
5+
* Streaming of SELECT responses. `client/Conn.ExecuteSelectStreaming()` added. [#560](https://github.com/go-mysql-org/go-mysql/pull/560) ([atercattus](https://github.com/atercattus))
6+
* Migation from travis.ci to github actions. [#559](https://github.com/go-mysql-org/go-mysql/pull/559) ([atercattus](https://github.com/atercattus))
7+
* Output sorted mysql gtid. [#500](https://github.com/go-mysql-org/go-mysql/pull/500) ([zr-hebo](https://github.com/zr-hebo))
8+
* Add skipped columns information. [#505](https://github.com/go-mysql-org/go-mysql/pull/505) ([laskoviymishka](https://github.com/laskoviymishka))
9+
* Feat: support disable retry sync for canal. [#507](https://github.com/go-mysql-org/go-mysql/pull/507) ([everpcpc](https://github.com/everpcpc))
10+
* Update README.md. [#511](https://github.com/go-mysql-org/go-mysql/pull/511) ([TennyZhuang](https://github.com/TennyZhuang))
11+
* Add function to extend replication options. [#508](https://github.com/go-mysql-org/go-mysql/pull/508) ([wefen](https://github.com/wefen))
12+
13+
### Tag v1.1.0 (2020.07.17)
14+
* Update .travis.yml (go 1.14 and tip). [#510](https://github.com/go-mysql-org/go-mysql/pull/510) ([atercattus](https://github.com/atercattus))
15+
* Update README.md. [#509](https://github.com/go-mysql-org/go-mysql/pull/509) ([atercattus](https://github.com/atercattus))
16+
* A lot of memory allocation optimizations. Changed public API for `mysql/Resultset` type. [#466](https://github.com/go-mysql-org/go-mysql/pull/466) ([atercattus](https://github.com/atercattus))
17+
18+
### Tag v1.0.0 (2020.07.17)
19+
Add SemVer

README.md

+41-7
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,29 @@
22

33
A pure go library to handle MySQL network protocol and replication.
44

5-
## Call for Committer/Maintainer
5+
![semver](https://img.shields.io/github/v/tag/go-mysql-org/go-mysql)
6+
![example workflow](https://github.com/go-mysql-org/go-mysql/actions/workflows/ci.yml/badge.svg)
7+
![gomod version](https://img.shields.io/github/go-mod/go-version/go-mysql-org/go-mysql/master)
68

7-
Sorry that I have no enough time to maintain this project wholly, if you like this project and want to help me improve it continuously, please contact me through email ([email protected]).
9+
## How to migrate to this repo
10+
To change the used package in your repo it's enough to add this `replace` directive to your `go.mod`:
11+
```
12+
replace github.com/siddontang/go-mysql => github.com/go-mysql-org/go-mysql v1.1.1
13+
```
814

9-
Requirement: In the email, you should list somethings(including but not limited to below) to make me believe we can work together.
15+
v.1.1.1 - is the last tag in repo, feel free to choose what you want.
1016

11-
+ Your GitHub ID
12-
+ The contributions to go-mysql before, including PRs or Issues.
13-
+ The reason why you can improve go-mysql.
14-
17+
## Changelog
18+
This repo uses [Changelog](CHANGELOG.md).
19+
20+
---
21+
# Content
22+
* [Slave replication](#replication)
23+
* [Incremental dumping](#canal)
24+
* [Client](#client)
25+
* [Fake server](#server)
26+
* [Failover](#failover)
27+
* [database/sql like driver](#driver)
1528

1629
## Replication
1730

@@ -197,6 +210,27 @@ Tested MySQL versions for the client include:
197210
- 5.7.x
198211
- 8.0.x
199212

213+
### Example for SELECT streaming (v.1.1.1)
214+
You can use also streaming for large SELECT responses.
215+
The callback function will be called for every result row without storing the whole resultset in memory.
216+
`result.Fields` will be filled before the first callback call.
217+
218+
```go
219+
// ...
220+
var result mysql.Result
221+
err := conn.ExecuteSelectStreaming(`select id, name from table LIMIT 100500`, &result, func(row []mysql.FieldValue) error {
222+
for idx, val := range row {
223+
field := result.Fields[idx]
224+
// You must not save FieldValue.AsString() value after this callback is done.
225+
// Copy it if you need.
226+
// ...
227+
}
228+
return false, nil
229+
})
230+
231+
// ...
232+
```
233+
200234
## Server
201235

202236
Server package supplies a framework to implement a simple MySQL server which can handle the packets from the MySQL client.

canal/canal.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ func (c *Canal) Close() {
249249
c.conn = nil
250250
c.connLock.Unlock()
251251

252-
c.eventHandler.OnPosSynced(c.master.Position(), c.master.GTIDSet(), true)
252+
_ = c.eventHandler.OnPosSynced(c.master.Position(), c.master.GTIDSet(), true)
253253
}
254254

255255
func (c *Canal) WaitDumpDone() <-chan struct{} {

canal/canal_test.go

100755100644
+22-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ type canalTestSuite struct {
2626

2727
var _ = Suite(&canalTestSuite{})
2828

29+
const (
30+
miA = 0
31+
miB = -1
32+
miC = 1
33+
34+
umiA = 0
35+
umiB = 1
36+
umiC = 16777215
37+
)
38+
2939
func (s *canalTestSuite) SetUpSuite(c *C) {
3040
cfg := NewDefaultConfig()
3141
cfg.Addr = fmt.Sprintf("%s:3306", *testHost)
@@ -62,7 +72,11 @@ func (s *canalTestSuite) SetUpSuite(c *C) {
6272
s.execute(c, sql)
6373

6474
s.execute(c, "DELETE FROM test.canal_test")
65-
s.execute(c, "INSERT INTO test.canal_test (content, name, mi, umi) VALUES (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?)", "1", "a", 0, 0, `\0\ndsfasdf`, "b", 1, 16777215, "", "c", -1, 1)
75+
s.execute(c, "INSERT INTO test.canal_test (content, name, mi, umi) VALUES (?, ?, ?, ?), (?, ?, ?, ?), (?, ?, ?, ?)",
76+
"1", "a", miA, umiA,
77+
`\0\ndsfasdf`, "b", miC, umiC,
78+
"", "c", miB, umiB,
79+
)
6680

6781
s.execute(c, "SET GLOBAL binlog_format = 'ROW'")
6882

@@ -99,7 +113,7 @@ type testEventHandler struct {
99113
func (h *testEventHandler) OnRow(e *RowsEvent) error {
100114
log.Infof("OnRow %s %v\n", e.Action, e.Rows)
101115
umi, ok := e.Rows[0][4].(uint32) // 4th col is umi. mysqldump gives uint64 instead of uint32
102-
if ok && (umi != 0 && umi != 1 && umi != 16777215) {
116+
if ok && (umi != umiA && umi != umiB && umi != umiC) {
103117
return fmt.Errorf("invalid unsigned medium int %d", umi)
104118
}
105119
return nil
@@ -119,7 +133,11 @@ func (s *canalTestSuite) TestCanal(c *C) {
119133
for i := 1; i < 10; i++ {
120134
s.execute(c, "INSERT INTO test.canal_test (name) VALUES (?)", fmt.Sprintf("%d", i))
121135
}
122-
s.execute(c, "INSERT INTO test.canal_test (mi,umi) VALUES (?,?), (?,?), (?,?)", 0, 0, -1, 16777215, 1, 1)
136+
s.execute(c, "INSERT INTO test.canal_test (mi,umi) VALUES (?,?), (?,?), (?,?)",
137+
miA, umiA,
138+
miC, umiC,
139+
miB, umiB,
140+
)
123141
s.execute(c, "ALTER TABLE test.canal_test ADD `age` INT(5) NOT NULL AFTER `name`")
124142
s.execute(c, "INSERT INTO test.canal_test (name,age) VALUES (?,?)", "d", "18")
125143

@@ -283,8 +301,8 @@ func TestDropTableExp(t *testing.T) {
283301
}
284302
}
285303
}
286-
func TestWithoutSchemeExp(t *testing.T) {
287304

305+
func TestWithoutSchemeExp(t *testing.T) {
288306
cases := []replication.QueryEvent{
289307
replication.QueryEvent{
290308
Schema: []byte("test"),

canal/sync.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func parseStmt(stmt ast.StmtNode) (ns []*node) {
227227
}
228228
ns = []*node{n}
229229
}
230-
return
230+
return ns
231231
}
232232

233233
func (c *Canal) updateTable(db, table string) (err error) {

client/auth.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (c *Conn) readInitialHandshake() error {
4646
pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1
4747

4848
// connection id length is 4
49-
c.connectionID = uint32(binary.LittleEndian.Uint32(data[pos : pos+4]))
49+
c.connectionID = binary.LittleEndian.Uint32(data[pos : pos+4])
5050
pos += 4
5151

5252
c.salt = []byte{}
@@ -106,7 +106,7 @@ func (c *Conn) readInitialHandshake() error {
106106
// generate auth response data according to auth plugin
107107
//
108108
// NOTE: the returned boolean value indicates whether to add a \NUL to the end of data.
109-
// it is quite tricky because MySQl server expects different formats of responses in different auth situations.
109+
// it is quite tricky because MySQL server expects different formats of responses in different auth situations.
110110
// here the \NUL needs to be added when sending back the empty password or cleartext password in 'sha256_password'
111111
// authentication.
112112
func (c *Conn) genAuthResponse(authData []byte) ([]byte, bool, error) {
@@ -199,7 +199,7 @@ func (c *Conn) writeAuthHandshake() error {
199199

200200
// Charset [1 byte]
201201
// use default collation id 33 here, is utf-8
202-
data[12] = byte(DEFAULT_COLLATION_ID)
202+
data[12] = DEFAULT_COLLATION_ID
203203

204204
// SSL Connection Request Packet
205205
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest

client/client_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ func (s *clientTestSuite) TestStmt_Select(c *C) {
289289

290290
e, _ = result.GetStringByName(0, "e")
291291
c.Assert(e, Equals, "test1")
292-
293292
}
294293

295294
func (s *clientTestSuite) TestStmt_NULL(c *C) {
@@ -309,11 +308,13 @@ func (s *clientTestSuite) TestStmt_NULL(c *C) {
309308

310309
str = `select * from mixer_test_stmt where id = ?`
311310
stmt, err = s.c.Prepare(str)
311+
c.Assert(err, IsNil)
312+
312313
defer stmt.Close()
313314

315+
result, err = stmt.Execute(2)
314316
c.Assert(err, IsNil)
315317

316-
result, err = stmt.Execute(2)
317318
b, err := result.IsNullByName(0, "id")
318319
c.Assert(err, IsNil)
319320
c.Assert(b, Equals, false)

client/conn.go

+25
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type Conn struct {
3333
connectionID uint32
3434
}
3535

36+
// This function will be called for every row in resultset from ExecuteSelectStreaming.
37+
type SelectPerRowCallback func(row []FieldValue) error
38+
3639
func getNetProto(addr string) string {
3740
proto := "tcp"
3841
if strings.Contains(addr, "/") {
@@ -165,6 +168,28 @@ func (c *Conn) Execute(command string, args ...interface{}) (*Result, error) {
165168
}
166169
}
167170

171+
// ExecuteSelectStreaming will call perRowCallback for every row in resultset
172+
// WITHOUT saving any row data to Result.{Values/RawPkg/RowDatas} fields.
173+
//
174+
// ExecuteSelectStreaming should be used only for SELECT queries with a large response resultset for memory preserving.
175+
//
176+
// Example:
177+
//
178+
// var result mysql.Result
179+
// conn.ExecuteSelectStreaming(`SELECT ... LIMIT 100500`, &result, func(row []mysql.FieldValue) error {
180+
// // Use the row as you want.
181+
// // You must not save FieldValue.AsString() value after this callback is done. Copy it if you need.
182+
// return nil
183+
// })
184+
//
185+
func (c *Conn) ExecuteSelectStreaming(command string, result *Result, perRowCallback SelectPerRowCallback) error {
186+
if err := c.writeCommandStr(COM_QUERY, command); err != nil {
187+
return errors.Trace(err)
188+
}
189+
190+
return c.readResultStreaming(false, result, perRowCallback)
191+
}
192+
168193
func (c *Conn) Begin() error {
169194
_, err := c.exec("BEGIN")
170195
return errors.Trace(err)

0 commit comments

Comments
 (0)