Skip to content

Commit 5ba21b7

Browse files
committed
Encode connection attribute only once.
1 parent 4e1c200 commit 5ba21b7

File tree

6 files changed

+70
-40
lines changed

6 files changed

+70
-40
lines changed

‎connection.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type mysqlConn struct{
2727
affectedRowsuint64
2828
insertIduint64
2929
cfg*Config
30+
connector*connector
3031
maxAllowedPacketint
3132
maxWriteSizeint
3233
writeTimeout time.Duration

‎connector.go‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,54 @@ package mysql
1111
import (
1212
"context"
1313
"database/sql/driver"
14+
"fmt"
1415
"net"
16+
"os"
17+
"strconv"
18+
"strings"
1519
)
1620

1721
typeconnectorstruct{
18-
cfg*Config// immutable private copy.
22+
cfg*Config// immutable private copy.
23+
encodedAttributesstring// Encoded connection attributes.
24+
}
25+
26+
funcencodeConnectionAttributes(textAttributesstring) string{
27+
connAttrsBuf:=make([]byte, 0, 251)
28+
29+
// default connection attributes
30+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrClientName)
31+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrClientNameValue)
32+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrOS)
33+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrOSValue)
34+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPlatform)
35+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPlatformValue)
36+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPid)
37+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, strconv.Itoa(os.Getpid()))
38+
39+
// user-defined connection attributes
40+
for_, connAttr:=rangestrings.Split(textAttributes, ","){
41+
attr:=strings.SplitN(connAttr, ":", 2)
42+
iflen(attr) !=2{
43+
continue
44+
}
45+
for_, v:=rangeattr{
46+
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, v)
47+
}
48+
}
49+
50+
returnstring(connAttrsBuf)
51+
}
52+
53+
funcnewConnector(cfg*Config) (*connector, error){
54+
encodedAttributes:=encodeConnectionAttributes(cfg.ConnectionAttributes)
55+
iflen(encodedAttributes) >250{
56+
returnnil, fmt.Errorf("connection attributes are longer than 250 bytes: %dbytes (%q)", len(encodedAttributes), cfg.ConnectionAttributes)
57+
}
58+
return&connector{
59+
cfg: cfg,
60+
encodedAttributes: encodedAttributes,
61+
}, nil
1962
}
2063

2164
// Connect implements driver.Connector interface.
@@ -29,6 +72,7 @@ func (c *connector) Connect(ctx context.Context) (driver.Conn, error){
2972
maxWriteSize: maxPacketSize-1,
3073
closech: make(chanstruct{}),
3174
cfg: c.cfg,
75+
connector: c,
3276
}
3377
mc.parseTime=mc.cfg.ParseTime
3478

‎connector_test.go‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import (
88
)
99

1010
funcTestConnectorReturnsTimeout(t*testing.T){
11-
connector:=&connector{&Config{
11+
connector, err:=newConnector(&Config{
1212
Net: "tcp",
1313
Addr: "1.1.1.1:1234",
1414
Timeout: 10*time.Millisecond,
15-
}}
15+
})
16+
iferr!=nil{
17+
t.Fatal(err)
18+
}
1619

17-
_, err:=connector.Connect(context.Background())
20+
_, err=connector.Connect(context.Background())
1821
iferr==nil{
1922
t.Fatal("error expected")
2023
}

‎driver.go‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error){
8585
iferr!=nil{
8686
returnnil, err
8787
}
88-
c:=&connector{
89-
cfg: cfg,
88+
c, err:=newConnector(cfg)
89+
iferr!=nil{
90+
returnnil, err
9091
}
9192
returnc.Connect(context.Background())
9293
}
@@ -103,7 +104,7 @@ func NewConnector(cfg *Config) (driver.Connector, error){
103104
iferr:=cfg.normalize(); err!=nil{
104105
returnnil, err
105106
}
106-
return&connector{cfg: cfg}, nil
107+
returnnewConnector(cfg)
107108
}
108109

109110
// OpenConnector implements driver.DriverContext.
@@ -112,7 +113,5 @@ func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error){
112113
iferr!=nil{
113114
returnnil, err
114115
}
115-
return&connector{
116-
cfg: cfg,
117-
}, nil
116+
returnnewConnector(cfg)
118117
}

‎packets.go‎

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ import (
1818
"fmt"
1919
"io"
2020
"math"
21-
"os"
22-
"strconv"
23-
"strings"
2421
"time"
2522
)
2623

@@ -322,31 +319,12 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
322319
pktLen+=n+1
323320
}
324321

325-
connAttrsBuf:=make([]byte, 0, 100)
326-
327-
// default connection attributes
328-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrClientName)
329-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrClientNameValue)
330-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrOS)
331-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrOSValue)
332-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPlatform)
333-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPlatformValue)
334-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, connAttrPid)
335-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, strconv.Itoa(os.Getpid()))
336-
337-
// user-defined connection attributes
338-
for_, connAttr:=rangestrings.Split(mc.cfg.ConnectionAttributes, ","){
339-
attr:=strings.Split(connAttr, ":")
340-
iflen(attr) !=2{
341-
continue
342-
}
343-
for_, v:=rangeattr{
344-
connAttrsBuf=appendLengthEncodedString(connAttrsBuf, v)
345-
}
346-
}
347-
348322
// 1 byte to store length of all key-values
349-
pktLen+=len(connAttrsBuf) +1
323+
// NOTE: Actually, this is length encoded integer.
324+
// But we support only len(connAttrBuf) < 251 for now because takeSmallBuffer
325+
// doesn't support buffer size more than 4096 bytes.
326+
// TODO(methane): Rewrite buffer management.
327+
pktLen+=1+len(mc.connector.encodedAttributes)
350328

351329
// Calculate packet length and get buffer with that size
352330
data, err:=mc.buf.takeSmallBuffer(pktLen+4)
@@ -425,9 +403,9 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
425403
pos++
426404

427405
// Connection Attributes
428-
data[pos] =byte(len(connAttrsBuf))
406+
data[pos] =byte(len(mc.connector.encodedAttributes))
429407
pos++
430-
pos+=copy(data[pos:], connAttrsBuf)
408+
pos+=copy(data[pos:], []byte(mc.connector.encodedAttributes))
431409

432410
// Send Auth packet
433411
returnmc.writePacket(data[:pos])

‎packets_test.go‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,14 @@ var _ net.Conn = new(mockConn)
9696

9797
funcnewRWMockConn(sequenceuint8) (*mockConn, *mysqlConn){
9898
conn:=new(mockConn)
99+
connector, err:=newConnector(NewConfig())
100+
iferr!=nil{
101+
panic(err)
102+
}
99103
mc:=&mysqlConn{
100104
buf: newBuffer(conn),
101-
cfg: NewConfig(),
105+
cfg: connector.cfg,
106+
connector: connector,
102107
netConn: conn,
103108
closech: make(chanstruct{}),
104109
maxAllowedPacket: defaultMaxAllowedPacket,

0 commit comments

Comments
(0)