mirror of
https://github.com/documize/community.git
synced 2025-07-20 13:49:42 +02:00
Updated Go MySQL driver library
This commit is contained in:
parent
d04becc1a3
commit
f3df43efe0
32 changed files with 7413 additions and 867 deletions
145
vendor/github.com/go-sql-driver/mysql/packets.go
generated
vendored
145
vendor/github.com/go-sql-driver/mysql/packets.go
generated
vendored
|
@ -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 {
|
||||
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 {
|
||||
|
@ -154,15 +183,15 @@ func (mc *mysqlConn) writePacket(data []byte) error {
|
|||
|
||||
// Handshake Initialization Packet
|
||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
|
||||
func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
||||
data, err := mc.readPacket()
|
||||
func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
|
||||
data, err = mc.readPacket()
|
||||
if err != nil {
|
||||
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
|
||||
// in connection initialization we don't risk retrying non-idempotent actions.
|
||||
if err == ErrInvalidConn {
|
||||
return nil, "", driver.ErrBadConn
|
||||
}
|
||||
return nil, "", err
|
||||
return
|
||||
}
|
||||
|
||||
if data[0] == iERR {
|
||||
|
@ -194,11 +223,14 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||
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
|
||||
|
||||
plugin := ""
|
||||
if len(data) > pos {
|
||||
// character set [1 byte]
|
||||
// status flags [2 bytes]
|
||||
|
@ -236,8 +268,6 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||
return b[:], plugin, nil
|
||||
}
|
||||
|
||||
plugin = defaultAuthPlugin
|
||||
|
||||
// make a memory safe copy of the cipher slice
|
||||
var b [8]byte
|
||||
copy(b[:], authData)
|
||||
|
@ -246,7 +276,7 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||
|
||||
// Client Authentication Packet
|
||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
|
||||
func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool, plugin string) error {
|
||||
func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string) error {
|
||||
// Adjust client flags based on server support
|
||||
clientFlags := clientProtocol41 |
|
||||
clientSecureConn |
|
||||
|
@ -272,7 +302,8 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
|
||||
// encode length of the auth plugin data
|
||||
var authRespLEIBuf [9]byte
|
||||
authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(len(authResp)))
|
||||
authRespLen := len(authResp)
|
||||
authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(authRespLen))
|
||||
if len(authRespLEI) > 1 {
|
||||
// if the length can not be written in 1 byte, it must be written as a
|
||||
// length encoded integer
|
||||
|
@ -280,9 +311,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
}
|
||||
|
||||
pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
|
||||
if addNUL {
|
||||
pktLen++
|
||||
}
|
||||
|
||||
// To specify a db name
|
||||
if n := len(mc.cfg.DBName); n > 0 {
|
||||
|
@ -291,10 +319,10 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -333,6 +361,7 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
if err := tlsConn.Handshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
mc.rawConn = mc.netConn
|
||||
mc.netConn = tlsConn
|
||||
mc.buf.nc = tlsConn
|
||||
}
|
||||
|
@ -353,10 +382,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
// Auth Data [length encoded integer]
|
||||
pos += copy(data[pos:], authRespLEI)
|
||||
pos += copy(data[pos:], authResp)
|
||||
if addNUL {
|
||||
data[pos] = 0x00
|
||||
pos++
|
||||
}
|
||||
|
||||
// Databasename [null terminated string]
|
||||
if len(mc.cfg.DBName) > 0 {
|
||||
|
@ -367,30 +392,24 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||
|
||||
pos += copy(data[pos:], plugin)
|
||||
data[pos] = 0x00
|
||||
pos++
|
||||
|
||||
// Send Auth packet
|
||||
return mc.writePacket(data)
|
||||
return mc.writePacket(data[:pos])
|
||||
}
|
||||
|
||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
|
||||
func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte, addNUL bool) error {
|
||||
func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
|
||||
pktLen := 4 + len(authData)
|
||||
if addNUL {
|
||||
pktLen++
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// Add the auth data [EOF]
|
||||
copy(data[4:], authData)
|
||||
if addNUL {
|
||||
data[pktLen-1] = 0x00
|
||||
}
|
||||
|
||||
return mc.writePacket(data)
|
||||
}
|
||||
|
||||
|
@ -402,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
|
||||
}
|
||||
|
||||
|
@ -421,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
|
||||
}
|
||||
|
||||
|
@ -442,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
|
||||
}
|
||||
|
||||
|
@ -482,7 +501,7 @@ func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
|
|||
return data[1:], "", err
|
||||
|
||||
case iEOF:
|
||||
if len(data) < 1 {
|
||||
if len(data) == 1 {
|
||||
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
|
||||
return nil, "mysql_old_password", nil
|
||||
}
|
||||
|
@ -898,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
|
||||
|
@ -908,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
|
||||
}
|
||||
|
||||
|
@ -942,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
|
||||
|
@ -951,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
|
||||
|
@ -999,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
|
||||
|
@ -1091,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)
|
||||
|
@ -1261,7 +1302,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
|
|||
rows.rs.columns[i].decimals,
|
||||
)
|
||||
}
|
||||
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true)
|
||||
dest[i], err = formatBinaryTime(data[pos:pos+int(num)], dstlen)
|
||||
case rows.mc.parseTime:
|
||||
dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
|
||||
default:
|
||||
|
@ -1281,7 +1322,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
|
|||
)
|
||||
}
|
||||
}
|
||||
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, false)
|
||||
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue