summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-sql-driver/mysql/packets.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-sql-driver/mysql/packets.go')
-rw-r--r--vendor/github.com/go-sql-driver/mysql/packets.go106
1 files changed, 81 insertions, 25 deletions
diff --git a/vendor/github.com/go-sql-driver/mysql/packets.go b/vendor/github.com/go-sql-driver/mysql/packets.go
index 9ed6408509..82ad7a2009 100644
--- a/vendor/github.com/go-sql-driver/mysql/packets.go
+++ b/vendor/github.com/go-sql-driver/mysql/packets.go
@@ -51,7 +51,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
mc.sequence++
// packets with length 0 terminate a previous packet which is a
- // multiple of (2^24)−1 bytes long
+ // multiple of (2^24)-1 bytes long
if pktLen == 0 {
// there was no previous packet
if prevData == nil {
@@ -96,6 +96,35 @@ func (mc *mysqlConn) writePacket(data []byte) error {
return ErrPktTooLarge
}
+ // Perform a stale connection check. We only perform this check for
+ // the first query on a connection that has been checked out of the
+ // connection pool: a fresh connection from the pool is more likely
+ // to be stale, and it has not performed any previous writes that
+ // could cause data corruption, so it's safe to return ErrBadConn
+ // if the check fails.
+ if mc.reset {
+ mc.reset = false
+ conn := mc.netConn
+ if mc.rawConn != nil {
+ conn = mc.rawConn
+ }
+ var err error
+ // If this connection has a ReadTimeout which we've been setting on
+ // reads, reset it to its default value before we attempt a non-blocking
+ // read, otherwise the scheduler will just time us out before we can read
+ if mc.cfg.ReadTimeout != 0 {
+ err = conn.SetReadDeadline(time.Time{})
+ }
+ if err == nil && mc.cfg.CheckConnLiveness {
+ err = connCheck(conn)
+ }
+ if err != nil {
+ errLog.Print("closing bad idle connection: ", err)
+ mc.Close()
+ return driver.ErrBadConn
+ }
+ }
+
for {
var size int
if pktLen >= maxPacketSize {
@@ -194,7 +223,11 @@ func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err erro
return nil, "", ErrOldProtocol
}
if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
- return nil, "", ErrNoTLS
+ if mc.cfg.TLSConfig == "preferred" {
+ mc.cfg.tls = nil
+ } else {
+ return nil, "", ErrNoTLS
+ }
}
pos += 2
@@ -286,10 +319,10 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
}
// Calculate packet length and get buffer with that size
- data := mc.buf.takeSmallBuffer(pktLen + 4)
- if data == nil {
+ data, err := mc.buf.takeSmallBuffer(pktLen + 4)
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -328,6 +361,7 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
if err := tlsConn.Handshake(); err != nil {
return err
}
+ mc.rawConn = mc.netConn
mc.netConn = tlsConn
mc.buf.nc = tlsConn
}
@@ -367,10 +401,10 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
pktLen := 4 + len(authData)
- data := mc.buf.takeSmallBuffer(pktLen)
- if data == nil {
+ data, err := mc.buf.takeSmallBuffer(pktLen)
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -387,10 +421,10 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
// Reset Packet Sequence
mc.sequence = 0
- data := mc.buf.takeSmallBuffer(4 + 1)
- if data == nil {
+ data, err := mc.buf.takeSmallBuffer(4 + 1)
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -406,10 +440,10 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
mc.sequence = 0
pktLen := 1 + len(arg)
- data := mc.buf.takeBuffer(pktLen + 4)
- if data == nil {
+ data, err := mc.buf.takeBuffer(pktLen + 4)
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -427,10 +461,10 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
// Reset Packet Sequence
mc.sequence = 0
- data := mc.buf.takeSmallBuffer(4 + 1 + 4)
- if data == nil {
+ data, err := mc.buf.takeSmallBuffer(4 + 1 + 4)
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -883,7 +917,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
const minPktLen = 4 + 1 + 4 + 1 + 4
mc := stmt.mc
- // Determine threshould dynamically to avoid packet size shortage.
+ // Determine threshold dynamically to avoid packet size shortage.
longDataSize := mc.maxAllowedPacket / (stmt.paramCount + 1)
if longDataSize < 64 {
longDataSize = 64
@@ -893,15 +927,17 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
mc.sequence = 0
var data []byte
+ var err error
if len(args) == 0 {
- data = mc.buf.takeBuffer(minPktLen)
+ data, err = mc.buf.takeBuffer(minPktLen)
} else {
- data = mc.buf.takeCompleteBuffer()
+ data, err = mc.buf.takeCompleteBuffer()
+ // In this case the len(data) == cap(data) which is used to optimise the flow below.
}
- if data == nil {
+ if err != nil {
// cannot take the buffer. Something must be wrong with the connection
- errLog.Print(ErrBusyBuffer)
+ errLog.Print(err)
return errBadConnNoWrite
}
@@ -927,7 +963,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
pos := minPktLen
var nullMask []byte
- if maskLen, typesLen := (len(args)+7)/8, 1+2*len(args); pos+maskLen+typesLen >= len(data) {
+ if maskLen, typesLen := (len(args)+7)/8, 1+2*len(args); pos+maskLen+typesLen >= cap(data) {
// buffer has to be extended but we don't know by how much so
// we depend on append after all data with known sizes fit.
// We stop at that because we deal with a lot of columns here
@@ -936,10 +972,11 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
copy(tmp[:pos], data[:pos])
data = tmp
nullMask = data[pos : pos+maskLen]
+ // No need to clean nullMask as make ensures that.
pos += maskLen
} else {
nullMask = data[pos : pos+maskLen]
- for i := 0; i < maskLen; i++ {
+ for i := range nullMask {
nullMask[i] = 0
}
pos += maskLen
@@ -984,6 +1021,22 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
)
}
+ case uint64:
+ paramTypes[i+i] = byte(fieldTypeLongLong)
+ paramTypes[i+i+1] = 0x80 // type is unsigned
+
+ if cap(paramValues)-len(paramValues)-8 >= 0 {
+ paramValues = paramValues[:len(paramValues)+8]
+ binary.LittleEndian.PutUint64(
+ paramValues[len(paramValues)-8:],
+ uint64(v),
+ )
+ } else {
+ paramValues = append(paramValues,
+ uint64ToBytes(uint64(v))...,
+ )
+ }
+
case float64:
paramTypes[i+i] = byte(fieldTypeDouble)
paramTypes[i+i+1] = 0x00
@@ -1076,7 +1129,10 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
// In that case we must build the data packet with the new values buffer
if valuesCap != cap(paramValues) {
data = append(data[:pos], paramValues...)
- mc.buf.buf = data
+ if err = mc.buf.store(data); err != nil {
+ errLog.Print(err)
+ return errBadConnNoWrite
+ }
}
pos += len(paramValues)