Skip to content

Commit 4613f32

Browse files
committed
read_timeout and write_timeout
1 parent 527bcd5 commit 4613f32

File tree

7 files changed

+53
-20
lines changed

7 files changed

+53
-20
lines changed

Diff for: benchmark_test.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,16 @@ func BenchmarkRoundtripBin(b *testing.B) {
215215
}
216216

217217
func BenchmarkInterpolation(b *testing.B) {
218+
cfg := &config{
219+
interpolateParams: true,
220+
loc: time.UTC,
221+
}
222+
218223
mc := &mysqlConn{
219-
cfg: &config{
220-
interpolateParams: true,
221-
loc: time.UTC,
222-
},
224+
cfg: cfg,
223225
maxPacketAllowed: maxPacketSize,
224226
maxWriteSize: maxPacketSize - 1,
225-
buf: newBuffer(nil),
227+
buf: newBuffer(nil, cfg),
226228
}
227229

228230
args := []driver.Value{

Diff for: buffer.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
package mysql
1010

1111
import "io"
12+
import "net"
13+
import "time"
1214

1315
const defaultBufSize = 4096
1416

@@ -22,13 +24,15 @@ type buffer struct {
2224
rd io.Reader
2325
idx int
2426
length int
27+
cfg *config
2528
}
2629

27-
func newBuffer(rd io.Reader) buffer {
30+
func newBuffer(rd io.Reader, cfg *config) buffer {
2831
var b [defaultBufSize]byte
2932
return buffer{
3033
buf: b[:],
3134
rd: rd,
35+
cfg: cfg,
3236
}
3337
}
3438

@@ -54,6 +58,12 @@ func (b *buffer) fill(need int) error {
5458
b.idx = 0
5559

5660
for {
61+
if conn, ok := b.rd.(net.Conn); ok && b.cfg.readTimeout > 0 {
62+
if err := conn.SetReadDeadline(time.Now().Add(b.cfg.readTimeout)); err != nil {
63+
return err
64+
}
65+
}
66+
5767
nn, err := b.rd.Read(b.buf[n:])
5868
n += nn
5969

Diff for: connection.go

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type config struct {
4343
loc *time.Location
4444
tls *tls.Config
4545
timeout time.Duration
46+
readTimeout time.Duration
47+
writeTimeout time.Duration
4648
collation uint8
4749
allowAllFiles bool
4850
allowOldPasswords bool

Diff for: driver.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
7979
}
8080
}
8181

82-
mc.buf = newBuffer(mc.netConn)
82+
mc.buf = newBuffer(mc.netConn, mc.cfg)
8383

8484
// Reading Handshake Initialization Packet
8585
cipher, err := mc.readInitPacket()

Diff for: packets.go

+6
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ func (mc *mysqlConn) writePacket(data []byte) error {
100100
data[3] = mc.sequence
101101

102102
// Write packet
103+
if mc.cfg.writeTimeout > 0 {
104+
if err := mc.netConn.SetWriteDeadline(time.Now().Add(mc.cfg.writeTimeout)); err != nil {
105+
return err
106+
}
107+
}
108+
103109
n, err := mc.netConn.Write(data[:4+size])
104110
if err == nil && n == 4+size {
105111
mc.sequence++

Diff for: utils.go

+13
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,19 @@ func parseDSNParams(cfg *config, params string) (err error) {
260260
return
261261
}
262262

263+
// I/O Timeouts
264+
case "read_timeout":
265+
cfg.readTimeout, err = time.ParseDuration(value)
266+
if err != nil {
267+
return
268+
}
269+
270+
case "write_timeout":
271+
cfg.writeTimeout, err = time.ParseDuration(value)
272+
if err != nil {
273+
return
274+
}
275+
263276
// TLS-Encryption
264277
case "tls":
265278
boolValue, isBool := readBool(value)

Diff for: utils_test.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ var testDSNs = []struct {
2222
out string
2323
loc *time.Location
2424
}{
25-
{"username:password@protocol(address)/dbname?param=value", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
26-
{"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:true interpolateParams:false}", time.UTC},
27-
{"user@unix(/path/to/socket)/dbname?charset=utf8", "&{user:user passwd: net:unix addr:/path/to/socket dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
28-
{"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
29-
{"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8mb4,utf8] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
30-
{"user:password@/dbname?loc=UTC&timeout=30s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 collation:224 allowAllFiles:true allowOldPasswords:true allowCleartextPasswords:false clientFoundRows:true columnsWithAlias:false interpolateParams:false}", time.UTC},
31-
{"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{user:user passwd:p@ss(word) net:tcp addr:[de:ad:be:ef::ca:fe]:80 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.Local},
32-
{"/dbname", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
33-
{"@/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
34-
{"/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
35-
{"", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
36-
{"user:p@/ssword@/", "&{user:user passwd:p@/ssword net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
37-
{"unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p tls:<nil> timeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
25+
{"username:password@protocol(address)/dbname?param=value", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
26+
{"username:password@protocol(address)/dbname?param=value&columnsWithAlias=true", "&{user:username passwd:password net:protocol addr:address dbname:dbname params:map[param:value] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:true interpolateParams:false}", time.UTC},
27+
{"user@unix(/path/to/socket)/dbname?charset=utf8", "&{user:user passwd: net:unix addr:/path/to/socket dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
28+
{"user:password@tcp(localhost:5555)/dbname?charset=utf8&tls=true", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
29+
{"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify", "&{user:user passwd:password net:tcp addr:localhost:5555 dbname:dbname params:map[charset:utf8mb4,utf8] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
30+
{"user:password@/dbname?loc=UTC&timeout=30s&read_timeout=1s&write_timeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci", "&{user:user passwd:password net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:30000000000 readTimeout:1000000000 writeTimeout:1000000000 collation:224 allowAllFiles:true allowOldPasswords:true allowCleartextPasswords:false clientFoundRows:true columnsWithAlias:false interpolateParams:false}", time.UTC},
31+
{"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local", "&{user:user passwd:p@ss(word) net:tcp addr:[de:ad:be:ef::ca:fe]:80 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.Local},
32+
{"/dbname", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname:dbname params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
33+
{"@/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
34+
{"/", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
35+
{"", "&{user: passwd: net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
36+
{"user:p@/ssword@/", "&{user:user passwd:p@/ssword net:tcp addr:127.0.0.1:3306 dbname: params:map[] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
37+
{"unix/?arg=%2Fsome%2Fpath.ext", "&{user: passwd: net:unix addr:/tmp/mysql.sock dbname: params:map[arg:/some/path.ext] loc:%p tls:<nil> timeout:0 readTimeout:0 writeTimeout:0 collation:33 allowAllFiles:false allowOldPasswords:false allowCleartextPasswords:false clientFoundRows:false columnsWithAlias:false interpolateParams:false}", time.UTC},
3838
}
3939

4040
func TestDSNParser(t *testing.T) {

0 commit comments

Comments
 (0)