Skip to content

Commit b81e73c

Browse files
xiezhenyejulienschmidt
authored andcommitted
Add maxAllowedPacket DSN Parameter
Allows to set the driver-side max_packet_allowed value manually * add docs * add author, add test * fix AUTHOR file and README * change the param name from MaxPacketAllowed to MaxAllowedPacket * fix maxAllowedPacket param name in README * rename all maxPacketAllowed to maxAllowedPacket * fix doc format * fix doc
1 parent 1983bc3 commit b81e73c

9 files changed

+66
-35
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Stan Putrya <root.vagner at gmail.com>
4545
Stanley Gunawan <gunawan.stanley at gmail.com>
4646
Xiaobing Jiang <s7v7nislands at gmail.com>
4747
Xiuming Chen <cc at cxm.cc>
48+
Zhenye Xie <xiezhenye at gmail.com>
4849

4950
# Organizations
5051

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,15 @@ Default: 0
299299
I/O write timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*.
300300

301301

302+
##### `maxAllowedPacket`
303+
```
304+
Type: decimal number
305+
Default: 0
306+
```
307+
308+
Max packet size allowed in bytes. Use `maxAllowedPacket=0` to automatically fetch the `max_allowed_packet` variable from server.
309+
310+
302311
##### System Variables
303312

304313
All other parameters are interpreted as system variables:

benchmark_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ func BenchmarkInterpolation(b *testing.B) {
220220
InterpolateParams: true,
221221
Loc: time.UTC,
222222
},
223-
maxPacketAllowed: maxPacketSize,
223+
maxAllowedPacket: maxPacketSize,
224224
maxWriteSize: maxPacketSize - 1,
225225
buf: newBuffer(nil),
226226
}

connection.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type mysqlConn struct {
2222
affectedRows uint64
2323
insertId uint64
2424
cfg *Config
25-
maxPacketAllowed int
25+
maxAllowedPacket int
2626
maxWriteSize int
2727
writeTimeout time.Duration
2828
flags clientFlag
@@ -246,7 +246,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
246246
return "", driver.ErrSkip
247247
}
248248

249-
if len(buf)+4 > mc.maxPacketAllowed {
249+
if len(buf)+4 > mc.maxAllowedPacket {
250250
return "", driver.ErrSkip
251251
}
252252
}

connection_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
func TestInterpolateParams(t *testing.T) {
1717
mc := &mysqlConn{
1818
buf: newBuffer(nil),
19-
maxPacketAllowed: maxPacketSize,
19+
maxAllowedPacket: maxPacketSize,
2020
cfg: &Config{
2121
InterpolateParams: true,
2222
},
@@ -36,7 +36,7 @@ func TestInterpolateParams(t *testing.T) {
3636
func TestInterpolateParamsTooManyPlaceholders(t *testing.T) {
3737
mc := &mysqlConn{
3838
buf: newBuffer(nil),
39-
maxPacketAllowed: maxPacketSize,
39+
maxAllowedPacket: maxPacketSize,
4040
cfg: &Config{
4141
InterpolateParams: true,
4242
},
@@ -53,7 +53,7 @@ func TestInterpolateParamsTooManyPlaceholders(t *testing.T) {
5353
func TestInterpolateParamsPlaceholderInString(t *testing.T) {
5454
mc := &mysqlConn{
5555
buf: newBuffer(nil),
56-
maxPacketAllowed: maxPacketSize,
56+
maxAllowedPacket: maxPacketSize,
5757
cfg: &Config{
5858
InterpolateParams: true,
5959
},

driver.go

+13-9
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
5050

5151
// New mysqlConn
5252
mc := &mysqlConn{
53-
maxPacketAllowed: maxPacketSize,
53+
maxAllowedPacket: maxPacketSize,
5454
maxWriteSize: maxPacketSize - 1,
5555
}
5656
mc.cfg, err = ParseDSN(dsn)
@@ -109,15 +109,19 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
109109
return nil, err
110110
}
111111

112-
// Get max allowed packet size
113-
maxap, err := mc.getSystemVar("max_allowed_packet")
114-
if err != nil {
115-
mc.Close()
116-
return nil, err
112+
if mc.cfg.MaxAllowedPacket > 0 {
113+
mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket
114+
} else {
115+
// Get max allowed packet size
116+
maxap, err := mc.getSystemVar("max_allowed_packet")
117+
if err != nil {
118+
mc.Close()
119+
return nil, err
120+
}
121+
mc.maxAllowedPacket = stringToInt(maxap) - 1
117122
}
118-
mc.maxPacketAllowed = stringToInt(maxap) - 1
119-
if mc.maxPacketAllowed < maxPacketSize {
120-
mc.maxWriteSize = mc.maxPacketAllowed
123+
if mc.maxAllowedPacket < maxPacketSize {
124+
mc.maxWriteSize = mc.maxAllowedPacket
121125
}
122126

123127
// Handle DSN Params

dsn.go

+31-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"fmt"
1616
"net"
1717
"net/url"
18+
"strconv"
1819
"strings"
1920
"time"
2021
)
@@ -28,19 +29,20 @@ var (
2829

2930
// Config is a configuration parsed from a DSN string
3031
type Config struct {
31-
User string // Username
32-
Passwd string // Password (requires User)
33-
Net string // Network type
34-
Addr string // Network address (requires Net)
35-
DBName string // Database name
36-
Params map[string]string // Connection parameters
37-
Collation string // Connection collation
38-
Loc *time.Location // Location for time.Time values
39-
TLSConfig string // TLS configuration name
40-
tls *tls.Config // TLS configuration
41-
Timeout time.Duration // Dial timeout
42-
ReadTimeout time.Duration // I/O read timeout
43-
WriteTimeout time.Duration // I/O write timeout
32+
User string // Username
33+
Passwd string // Password (requires User)
34+
Net string // Network type
35+
Addr string // Network address (requires Net)
36+
DBName string // Database name
37+
Params map[string]string // Connection parameters
38+
Collation string // Connection collation
39+
Loc *time.Location // Location for time.Time values
40+
MaxAllowedPacket int // Max packet size allowed
41+
TLSConfig string // TLS configuration name
42+
tls *tls.Config // TLS configuration
43+
Timeout time.Duration // Dial timeout
44+
ReadTimeout time.Duration // I/O read timeout
45+
WriteTimeout time.Duration // I/O write timeout
4446

4547
AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE
4648
AllowCleartextPasswords bool // Allows the cleartext client side plugin
@@ -222,6 +224,17 @@ func (cfg *Config) FormatDSN() string {
222224
buf.WriteString(cfg.WriteTimeout.String())
223225
}
224226

227+
if cfg.MaxAllowedPacket > 0 {
228+
if hasParam {
229+
buf.WriteString("&maxAllowedPacket=")
230+
} else {
231+
hasParam = true
232+
buf.WriteString("?maxAllowedPacket=")
233+
}
234+
buf.WriteString(strconv.Itoa(cfg.MaxAllowedPacket))
235+
236+
}
237+
225238
// other params
226239
if cfg.Params != nil {
227240
for param, value := range cfg.Params {
@@ -496,7 +509,11 @@ func parseDSNParams(cfg *Config, params string) (err error) {
496509
if err != nil {
497510
return
498511
}
499-
512+
case "maxAllowedPacket":
513+
cfg.MaxAllowedPacket, err = strconv.Atoi(value)
514+
if err != nil {
515+
return
516+
}
500517
default:
501518
// lazy init
502519
if cfg.Params == nil {

dsn_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ var testDSNs = []struct {
3939
"user:password@tcp(localhost:5555)/dbname?charset=utf8mb4,utf8&tls=skip-verify",
4040
&Config{User: "user", Passwd: "password", Net: "tcp", Addr: "localhost:5555", DBName: "dbname", Params: map[string]string{"charset": "utf8mb4,utf8"}, Collation: "utf8_general_ci", Loc: time.UTC, TLSConfig: "skip-verify"},
4141
}, {
42-
"user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci",
43-
&Config{User: "user", Passwd: "password", Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8mb4_unicode_ci", Loc: time.UTC, Timeout: 30 * time.Second, ReadTimeout: time.Second, WriteTimeout: time.Second, AllowAllFiles: true, AllowOldPasswords: true, ClientFoundRows: true},
42+
"user:password@/dbname?loc=UTC&timeout=30s&readTimeout=1s&writeTimeout=1s&allowAllFiles=1&clientFoundRows=true&allowOldPasswords=TRUE&collation=utf8mb4_unicode_ci&maxAllowedPacket=16777216",
43+
&Config{User: "user", Passwd: "password", Net: "tcp", Addr: "127.0.0.1:3306", DBName: "dbname", Collation: "utf8mb4_unicode_ci", Loc: time.UTC, Timeout: 30 * time.Second, ReadTimeout: time.Second, WriteTimeout: time.Second, AllowAllFiles: true, AllowOldPasswords: true, ClientFoundRows: true, MaxAllowedPacket: 16777216},
4444
}, {
4545
"user:p@ss(word)@tcp([de:ad:be:ef::ca:fe]:80)/dbname?loc=Local",
4646
&Config{User: "user", Passwd: "p@ss(word)", Net: "tcp", Addr: "[de:ad:be:ef::ca:fe]:80", DBName: "dbname", Collation: "utf8_general_ci", Loc: time.Local},

packets.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
8080
func (mc *mysqlConn) writePacket(data []byte) error {
8181
pktLen := len(data) - 4
8282

83-
if pktLen > mc.maxPacketAllowed {
83+
if pktLen > mc.maxAllowedPacket {
8484
return ErrPktTooLarge
8585
}
8686

@@ -786,7 +786,7 @@ func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {
786786

787787
// http://dev.mysql.com/doc/internals/en/com-stmt-send-long-data.html
788788
func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
789-
maxLen := stmt.mc.maxPacketAllowed - 1
789+
maxLen := stmt.mc.maxAllowedPacket - 1
790790
pktLen := maxLen
791791

792792
// After the header (bytes 0-3) follows before the data:
@@ -977,7 +977,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
977977
paramTypes[i+i] = fieldTypeString
978978
paramTypes[i+i+1] = 0x00
979979

980-
if len(v) < mc.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
980+
if len(v) < mc.maxAllowedPacket-pos-len(paramValues)-(len(args)-(i+1))*64 {
981981
paramValues = appendLengthEncodedInteger(paramValues,
982982
uint64(len(v)),
983983
)
@@ -999,7 +999,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
999999
paramTypes[i+i] = fieldTypeString
10001000
paramTypes[i+i+1] = 0x00
10011001

1002-
if len(v) < mc.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
1002+
if len(v) < mc.maxAllowedPacket-pos-len(paramValues)-(len(args)-(i+1))*64 {
10031003
paramValues = appendLengthEncodedInteger(paramValues,
10041004
uint64(len(v)),
10051005
)

0 commit comments

Comments
 (0)