mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 05:25:15 +01:00 
			
		
		
		
	upgrade go-sql-driver/mysql to fix invalid connection error (#5748)
should fix #5736
This commit is contained in:
		
							parent
							
								
									5ac6da3c41
								
							
						
					
					
						commit
						477a80f658
					
				
							
								
								
									
										4
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							@ -383,11 +383,11 @@
 | 
				
			|||||||
  revision = "a77f45a7ce909c0ff14b28279fa1a2b674acb70f"
 | 
					  revision = "a77f45a7ce909c0ff14b28279fa1a2b674acb70f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:747c1fcb10f8f6734551465ab73c6ed9c551aa6e66250fb6683d1624f554546a"
 | 
					  digest = "1:dce58f88343bd78f4d32dd9601aab4fa5d9994fd2cafa185c51bbd858851cdf9"
 | 
				
			||||||
  name = "github.com/go-sql-driver/mysql"
 | 
					  name = "github.com/go-sql-driver/mysql"
 | 
				
			||||||
  packages = ["."]
 | 
					  packages = ["."]
 | 
				
			||||||
  pruneopts = "NUT"
 | 
					  pruneopts = "NUT"
 | 
				
			||||||
  revision = "d523deb1b23d913de5bdada721a6071e71283618"
 | 
					  revision = "c45f530f8e7fe40f4687eaa50d0c8c5f1b66f9e0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:06d21295033f211588d0ad7ff391cc1b27e72b60cb6d4b7db0d70cffae4cf228"
 | 
					  digest = "1:06d21295033f211588d0ad7ff391cc1b27e72b60cb6d4b7db0d70cffae4cf228"
 | 
				
			||||||
 | 
				
			|||||||
@ -46,7 +46,7 @@ ignored = ["google.golang.org/appengine*"]
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[override]]
 | 
					[[override]]
 | 
				
			||||||
  name = "github.com/go-sql-driver/mysql"
 | 
					  name = "github.com/go-sql-driver/mysql"
 | 
				
			||||||
  revision = "d523deb1b23d913de5bdada721a6071e71283618"
 | 
					  revision = "c45f530f8e7fe40f4687eaa50d0c8c5f1b66f9e0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[override]]
 | 
					[[override]]
 | 
				
			||||||
  name = "github.com/mattn/go-sqlite3"
 | 
					  name = "github.com/mattn/go-sqlite3"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vendor/github.com/go-sql-driver/mysql/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/go-sql-driver/mysql/AUTHORS
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -35,6 +35,7 @@ Hanno Braun <mail at hannobraun.com>
 | 
				
			|||||||
Henri Yandell <flamefew at gmail.com>
 | 
					Henri Yandell <flamefew at gmail.com>
 | 
				
			||||||
Hirotaka Yamamoto <ymmt2005 at gmail.com>
 | 
					Hirotaka Yamamoto <ymmt2005 at gmail.com>
 | 
				
			||||||
ICHINOSE Shogo <shogo82148 at gmail.com>
 | 
					ICHINOSE Shogo <shogo82148 at gmail.com>
 | 
				
			||||||
 | 
					Ilia Cimpoes <ichimpoesh at gmail.com>
 | 
				
			||||||
INADA Naoki <songofacandy at gmail.com>
 | 
					INADA Naoki <songofacandy at gmail.com>
 | 
				
			||||||
Jacek Szwec <szwec.jacek at gmail.com>
 | 
					Jacek Szwec <szwec.jacek at gmail.com>
 | 
				
			||||||
James Harr <james.harr at gmail.com>
 | 
					James Harr <james.harr at gmail.com>
 | 
				
			||||||
@ -72,6 +73,9 @@ Shuode Li <elemount at qq.com>
 | 
				
			|||||||
Soroush Pour <me at soroushjp.com>
 | 
					Soroush Pour <me at soroushjp.com>
 | 
				
			||||||
Stan Putrya <root.vagner at gmail.com>
 | 
					Stan Putrya <root.vagner at gmail.com>
 | 
				
			||||||
Stanley Gunawan <gunawan.stanley at gmail.com>
 | 
					Stanley Gunawan <gunawan.stanley at gmail.com>
 | 
				
			||||||
 | 
					Steven Hartland <steven.hartland at multiplay.co.uk>
 | 
				
			||||||
 | 
					Thomas Wodarek <wodarekwebpage at gmail.com>
 | 
				
			||||||
 | 
					Tom Jenkinson <tom at tjenkinson.me>
 | 
				
			||||||
Xiangyu Hu <xiangyu.hu at outlook.com>
 | 
					Xiangyu Hu <xiangyu.hu at outlook.com>
 | 
				
			||||||
Xiaobing Jiang <s7v7nislands at gmail.com>
 | 
					Xiaobing Jiang <s7v7nislands at gmail.com>
 | 
				
			||||||
Xiuming Chen <cc at cxm.cc>
 | 
					Xiuming Chen <cc at cxm.cc>
 | 
				
			||||||
@ -87,3 +91,4 @@ Keybase Inc.
 | 
				
			|||||||
Percona LLC
 | 
					Percona LLC
 | 
				
			||||||
Pivotal Inc.
 | 
					Pivotal Inc.
 | 
				
			||||||
Stripe Inc.
 | 
					Stripe Inc.
 | 
				
			||||||
 | 
					Multiplay Ltd.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										44
									
								
								vendor/github.com/go-sql-driver/mysql/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/go-sql-driver/mysql/auth.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -234,64 +234,64 @@ func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) erro
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return mc.writeAuthSwitchPacket(enc, false)
 | 
						return mc.writeAuthSwitchPacket(enc)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
 | 
					func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) {
 | 
				
			||||||
	switch plugin {
 | 
						switch plugin {
 | 
				
			||||||
	case "caching_sha2_password":
 | 
						case "caching_sha2_password":
 | 
				
			||||||
		authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
 | 
							authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
 | 
				
			||||||
		return authResp, (authResp == nil), nil
 | 
							return authResp, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "mysql_old_password":
 | 
						case "mysql_old_password":
 | 
				
			||||||
		if !mc.cfg.AllowOldPasswords {
 | 
							if !mc.cfg.AllowOldPasswords {
 | 
				
			||||||
			return nil, false, ErrOldPassword
 | 
								return nil, ErrOldPassword
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Note: there are edge cases where this should work but doesn't;
 | 
							// Note: there are edge cases where this should work but doesn't;
 | 
				
			||||||
		// this is currently "wontfix":
 | 
							// this is currently "wontfix":
 | 
				
			||||||
		// https://github.com/go-sql-driver/mysql/issues/184
 | 
							// https://github.com/go-sql-driver/mysql/issues/184
 | 
				
			||||||
		authResp := scrambleOldPassword(authData[:8], mc.cfg.Passwd)
 | 
							authResp := append(scrambleOldPassword(authData[:8], mc.cfg.Passwd), 0)
 | 
				
			||||||
		return authResp, true, nil
 | 
							return authResp, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "mysql_clear_password":
 | 
						case "mysql_clear_password":
 | 
				
			||||||
		if !mc.cfg.AllowCleartextPasswords {
 | 
							if !mc.cfg.AllowCleartextPasswords {
 | 
				
			||||||
			return nil, false, ErrCleartextPassword
 | 
								return nil, ErrCleartextPassword
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
 | 
							// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
 | 
				
			||||||
		// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
 | 
							// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
 | 
				
			||||||
		return []byte(mc.cfg.Passwd), true, nil
 | 
							return append([]byte(mc.cfg.Passwd), 0), nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "mysql_native_password":
 | 
						case "mysql_native_password":
 | 
				
			||||||
		if !mc.cfg.AllowNativePasswords {
 | 
							if !mc.cfg.AllowNativePasswords {
 | 
				
			||||||
			return nil, false, ErrNativePassword
 | 
								return nil, ErrNativePassword
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
 | 
							// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
 | 
				
			||||||
		// Native password authentication only need and will need 20-byte challenge.
 | 
							// Native password authentication only need and will need 20-byte challenge.
 | 
				
			||||||
		authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
 | 
							authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
 | 
				
			||||||
		return authResp, false, nil
 | 
							return authResp, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "sha256_password":
 | 
						case "sha256_password":
 | 
				
			||||||
		if len(mc.cfg.Passwd) == 0 {
 | 
							if len(mc.cfg.Passwd) == 0 {
 | 
				
			||||||
			return nil, true, nil
 | 
								return []byte{0}, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
 | 
							if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
 | 
				
			||||||
			// write cleartext auth packet
 | 
								// write cleartext auth packet
 | 
				
			||||||
			return []byte(mc.cfg.Passwd), true, nil
 | 
								return append([]byte(mc.cfg.Passwd), 0), nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pubKey := mc.cfg.pubKey
 | 
							pubKey := mc.cfg.pubKey
 | 
				
			||||||
		if pubKey == nil {
 | 
							if pubKey == nil {
 | 
				
			||||||
			// request public key from server
 | 
								// request public key from server
 | 
				
			||||||
			return []byte{1}, false, nil
 | 
								return []byte{1}, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// encrypted password
 | 
							// encrypted password
 | 
				
			||||||
		enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
 | 
							enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
 | 
				
			||||||
		return enc, false, err
 | 
							return enc, err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		errLog.Print("unknown auth plugin:", plugin)
 | 
							errLog.Print("unknown auth plugin:", plugin)
 | 
				
			||||||
		return nil, false, ErrUnknownPlugin
 | 
							return nil, ErrUnknownPlugin
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -315,11 +315,11 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		plugin = newPlugin
 | 
							plugin = newPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		authResp, addNUL, err := mc.auth(authData, plugin)
 | 
							authResp, err := mc.auth(authData, plugin)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err = mc.writeAuthSwitchPacket(authResp, addNUL); err != nil {
 | 
							if err = mc.writeAuthSwitchPacket(authResp); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -352,7 +352,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
 | 
				
			|||||||
			case cachingSha2PasswordPerformFullAuthentication:
 | 
								case cachingSha2PasswordPerformFullAuthentication:
 | 
				
			||||||
				if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
 | 
									if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
 | 
				
			||||||
					// write cleartext auth packet
 | 
										// write cleartext auth packet
 | 
				
			||||||
					err = mc.writeAuthSwitchPacket([]byte(mc.cfg.Passwd), true)
 | 
										err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0))
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@ -360,13 +360,15 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
 | 
				
			|||||||
					pubKey := mc.cfg.pubKey
 | 
										pubKey := mc.cfg.pubKey
 | 
				
			||||||
					if pubKey == nil {
 | 
										if pubKey == nil {
 | 
				
			||||||
						// request public key from server
 | 
											// request public key from server
 | 
				
			||||||
						data := mc.buf.takeSmallBuffer(4 + 1)
 | 
											data, err := mc.buf.takeSmallBuffer(4 + 1)
 | 
				
			||||||
 | 
											if err != nil {
 | 
				
			||||||
 | 
												return err
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
						data[4] = cachingSha2PasswordRequestPublicKey
 | 
											data[4] = cachingSha2PasswordRequestPublicKey
 | 
				
			||||||
						mc.writePacket(data)
 | 
											mc.writePacket(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						// parse public key
 | 
											// parse public key
 | 
				
			||||||
						data, err := mc.readPacket()
 | 
											if data, err = mc.readPacket(); err != nil {
 | 
				
			||||||
						if err != nil {
 | 
					 | 
				
			||||||
							return err
 | 
												return err
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										49
									
								
								vendor/github.com/go-sql-driver/mysql/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/go-sql-driver/mysql/buffer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -22,17 +22,17 @@ const defaultBufSize = 4096
 | 
				
			|||||||
// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
 | 
					// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
 | 
				
			||||||
// Also highly optimized for this particular use case.
 | 
					// Also highly optimized for this particular use case.
 | 
				
			||||||
type buffer struct {
 | 
					type buffer struct {
 | 
				
			||||||
	buf     []byte
 | 
						buf     []byte // buf is a byte buffer who's length and capacity are equal.
 | 
				
			||||||
	nc      net.Conn
 | 
						nc      net.Conn
 | 
				
			||||||
	idx     int
 | 
						idx     int
 | 
				
			||||||
	length  int
 | 
						length  int
 | 
				
			||||||
	timeout time.Duration
 | 
						timeout time.Duration
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newBuffer allocates and returns a new buffer.
 | 
				
			||||||
func newBuffer(nc net.Conn) buffer {
 | 
					func newBuffer(nc net.Conn) buffer {
 | 
				
			||||||
	var b [defaultBufSize]byte
 | 
					 | 
				
			||||||
	return buffer{
 | 
						return buffer{
 | 
				
			||||||
		buf: b[:],
 | 
							buf: make([]byte, defaultBufSize),
 | 
				
			||||||
		nc:  nc,
 | 
							nc:  nc,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -105,43 +105,56 @@ func (b *buffer) readNext(need int) ([]byte, error) {
 | 
				
			|||||||
	return b.buf[offset:b.idx], nil
 | 
						return b.buf[offset:b.idx], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// returns a buffer with the requested size.
 | 
					// takeBuffer returns a buffer with the requested size.
 | 
				
			||||||
// If possible, a slice from the existing buffer is returned.
 | 
					// If possible, a slice from the existing buffer is returned.
 | 
				
			||||||
// Otherwise a bigger buffer is made.
 | 
					// Otherwise a bigger buffer is made.
 | 
				
			||||||
// Only one buffer (total) can be used at a time.
 | 
					// Only one buffer (total) can be used at a time.
 | 
				
			||||||
func (b *buffer) takeBuffer(length int) []byte {
 | 
					func (b *buffer) takeBuffer(length int) ([]byte, error) {
 | 
				
			||||||
	if b.length > 0 {
 | 
						if b.length > 0 {
 | 
				
			||||||
		return nil
 | 
							return nil, ErrBusyBuffer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test (cheap) general case first
 | 
						// test (cheap) general case first
 | 
				
			||||||
	if length <= defaultBufSize || length <= cap(b.buf) {
 | 
						if length <= cap(b.buf) {
 | 
				
			||||||
		return b.buf[:length]
 | 
							return b.buf[:length], nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if length < maxPacketSize {
 | 
						if length < maxPacketSize {
 | 
				
			||||||
		b.buf = make([]byte, length)
 | 
							b.buf = make([]byte, length)
 | 
				
			||||||
		return b.buf
 | 
							return b.buf, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return make([]byte, length)
 | 
					
 | 
				
			||||||
 | 
						// buffer is larger than we want to store.
 | 
				
			||||||
 | 
						return make([]byte, length), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// shortcut which can be used if the requested buffer is guaranteed to be
 | 
					// takeSmallBuffer is shortcut which can be used if length is
 | 
				
			||||||
// smaller than defaultBufSize
 | 
					// known to be smaller than defaultBufSize.
 | 
				
			||||||
// Only one buffer (total) can be used at a time.
 | 
					// Only one buffer (total) can be used at a time.
 | 
				
			||||||
func (b *buffer) takeSmallBuffer(length int) []byte {
 | 
					func (b *buffer) takeSmallBuffer(length int) ([]byte, error) {
 | 
				
			||||||
	if b.length > 0 {
 | 
						if b.length > 0 {
 | 
				
			||||||
		return nil
 | 
							return nil, ErrBusyBuffer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return b.buf[:length]
 | 
						return b.buf[:length], nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// takeCompleteBuffer returns the complete existing buffer.
 | 
					// takeCompleteBuffer returns the complete existing buffer.
 | 
				
			||||||
// This can be used if the necessary buffer size is unknown.
 | 
					// This can be used if the necessary buffer size is unknown.
 | 
				
			||||||
 | 
					// cap and len of the returned buffer will be equal.
 | 
				
			||||||
// Only one buffer (total) can be used at a time.
 | 
					// Only one buffer (total) can be used at a time.
 | 
				
			||||||
func (b *buffer) takeCompleteBuffer() []byte {
 | 
					func (b *buffer) takeCompleteBuffer() ([]byte, error) {
 | 
				
			||||||
	if b.length > 0 {
 | 
						if b.length > 0 {
 | 
				
			||||||
		return nil
 | 
							return nil, ErrBusyBuffer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return b.buf
 | 
						return b.buf, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// store stores buf, an updated buffer, if its suitable to do so.
 | 
				
			||||||
 | 
					func (b *buffer) store(buf []byte) error {
 | 
				
			||||||
 | 
						if b.length > 0 {
 | 
				
			||||||
 | 
							return ErrBusyBuffer
 | 
				
			||||||
 | 
						} else if cap(buf) <= maxPacketSize && cap(buf) > cap(b.buf) {
 | 
				
			||||||
 | 
							b.buf = buf[:cap(buf)]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										210
									
								
								vendor/github.com/go-sql-driver/mysql/connection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										210
									
								
								vendor/github.com/go-sql-driver/mysql/connection.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -9,6 +9,8 @@
 | 
				
			|||||||
package mysql
 | 
					package mysql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"database/sql"
 | 
				
			||||||
	"database/sql/driver"
 | 
						"database/sql/driver"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
@ -17,16 +19,6 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// a copy of context.Context for Go 1.7 and earlier
 | 
					 | 
				
			||||||
type mysqlContext interface {
 | 
					 | 
				
			||||||
	Done() <-chan struct{}
 | 
					 | 
				
			||||||
	Err() error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// defined in context.Context, but not used in this driver:
 | 
					 | 
				
			||||||
	// Deadline() (deadline time.Time, ok bool)
 | 
					 | 
				
			||||||
	// Value(key interface{}) interface{}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type mysqlConn struct {
 | 
					type mysqlConn struct {
 | 
				
			||||||
	buf              buffer
 | 
						buf              buffer
 | 
				
			||||||
	netConn          net.Conn
 | 
						netConn          net.Conn
 | 
				
			||||||
@ -43,7 +35,7 @@ type mysqlConn struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// for context support (Go 1.8+)
 | 
						// for context support (Go 1.8+)
 | 
				
			||||||
	watching bool
 | 
						watching bool
 | 
				
			||||||
	watcher  chan<- mysqlContext
 | 
						watcher  chan<- context.Context
 | 
				
			||||||
	closech  chan struct{}
 | 
						closech  chan struct{}
 | 
				
			||||||
	finished chan<- struct{}
 | 
						finished chan<- struct{}
 | 
				
			||||||
	canceled atomicError // set non-nil if conn is canceled
 | 
						canceled atomicError // set non-nil if conn is canceled
 | 
				
			||||||
@ -190,10 +182,10 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
 | 
				
			|||||||
		return "", driver.ErrSkip
 | 
							return "", driver.ErrSkip
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buf := mc.buf.takeCompleteBuffer()
 | 
						buf, err := mc.buf.takeCompleteBuffer()
 | 
				
			||||||
	if buf == nil {
 | 
						if err != nil {
 | 
				
			||||||
		// can not take the buffer. Something must be wrong with the connection
 | 
							// can not take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return "", ErrInvalidConn
 | 
							return "", ErrInvalidConn
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	buf = buf[:0]
 | 
						buf = buf[:0]
 | 
				
			||||||
@ -459,3 +451,193 @@ func (mc *mysqlConn) finish() {
 | 
				
			|||||||
	case <-mc.closech:
 | 
						case <-mc.closech:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Ping implements driver.Pinger interface
 | 
				
			||||||
 | 
					func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
 | 
				
			||||||
 | 
						if mc.closed.IsSet() {
 | 
				
			||||||
 | 
							errLog.Print(ErrInvalidConn)
 | 
				
			||||||
 | 
							return driver.ErrBadConn
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer mc.finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = mc.writeCommandPacket(comPing); err != nil {
 | 
				
			||||||
 | 
							return mc.markBadConn(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mc.readResultOK()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BeginTx implements driver.ConnBeginTx interface
 | 
				
			||||||
 | 
					func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
 | 
				
			||||||
 | 
						if err := mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer mc.finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if sql.IsolationLevel(opts.Isolation) != sql.LevelDefault {
 | 
				
			||||||
 | 
							level, err := mapIsolationLevel(opts.Isolation)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							err = mc.exec("SET TRANSACTION ISOLATION LEVEL " + level)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mc.begin(opts.ReadOnly)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
 | 
				
			||||||
 | 
						dargs, err := namedValueToValue(args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rows, err := mc.query(query, dargs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							mc.finish()
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rows.finish = mc.finish
 | 
				
			||||||
 | 
						return rows, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
 | 
				
			||||||
 | 
						dargs, err := namedValueToValue(args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer mc.finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mc.Exec(query, dargs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
 | 
				
			||||||
 | 
						if err := mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stmt, err := mc.Prepare(query)
 | 
				
			||||||
 | 
						mc.finish()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						select {
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
						case <-ctx.Done():
 | 
				
			||||||
 | 
							stmt.Close()
 | 
				
			||||||
 | 
							return nil, ctx.Err()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return stmt, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (stmt *mysqlStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
 | 
				
			||||||
 | 
						dargs, err := namedValueToValue(args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := stmt.mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rows, err := stmt.query(dargs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							stmt.mc.finish()
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rows.finish = stmt.mc.finish
 | 
				
			||||||
 | 
						return rows, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (stmt *mysqlStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
 | 
				
			||||||
 | 
						dargs, err := namedValueToValue(args)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := stmt.mc.watchCancel(ctx); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer stmt.mc.finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stmt.Exec(dargs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) watchCancel(ctx context.Context) error {
 | 
				
			||||||
 | 
						if mc.watching {
 | 
				
			||||||
 | 
							// Reach here if canceled,
 | 
				
			||||||
 | 
							// so the connection is already invalid
 | 
				
			||||||
 | 
							mc.cleanup()
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// When ctx is already cancelled, don't watch it.
 | 
				
			||||||
 | 
						if err := ctx.Err(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// When ctx is not cancellable, don't watch it.
 | 
				
			||||||
 | 
						if ctx.Done() == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// When watcher is not alive, can't watch it.
 | 
				
			||||||
 | 
						if mc.watcher == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mc.watching = true
 | 
				
			||||||
 | 
						mc.watcher <- ctx
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) startWatcher() {
 | 
				
			||||||
 | 
						watcher := make(chan context.Context, 1)
 | 
				
			||||||
 | 
						mc.watcher = watcher
 | 
				
			||||||
 | 
						finished := make(chan struct{})
 | 
				
			||||||
 | 
						mc.finished = finished
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								var ctx context.Context
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case ctx = <-watcher:
 | 
				
			||||||
 | 
								case <-mc.closech:
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case <-ctx.Done():
 | 
				
			||||||
 | 
									mc.cancel(ctx.Err())
 | 
				
			||||||
 | 
								case <-finished:
 | 
				
			||||||
 | 
								case <-mc.closech:
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
 | 
				
			||||||
 | 
						nv.Value, err = converter{}.ConvertValue(nv.Value)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ResetSession implements driver.SessionResetter.
 | 
				
			||||||
 | 
					// (From Go 1.10)
 | 
				
			||||||
 | 
					func (mc *mysqlConn) ResetSession(ctx context.Context) error {
 | 
				
			||||||
 | 
						if mc.closed.IsSet() {
 | 
				
			||||||
 | 
							return driver.ErrBadConn
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										208
									
								
								vendor/github.com/go-sql-driver/mysql/connection_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										208
									
								
								vendor/github.com/go-sql-driver/mysql/connection_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -1,208 +0,0 @@
 | 
				
			|||||||
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This Source Code Form is subject to the terms of the Mozilla Public
 | 
					 | 
				
			||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
 | 
					 | 
				
			||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build go1.8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mysql
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"database/sql"
 | 
					 | 
				
			||||||
	"database/sql/driver"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Ping implements driver.Pinger interface
 | 
					 | 
				
			||||||
func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
 | 
					 | 
				
			||||||
	if mc.closed.IsSet() {
 | 
					 | 
				
			||||||
		errLog.Print(ErrInvalidConn)
 | 
					 | 
				
			||||||
		return driver.ErrBadConn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer mc.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = mc.writeCommandPacket(comPing); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mc.readResultOK()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BeginTx implements driver.ConnBeginTx interface
 | 
					 | 
				
			||||||
func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
 | 
					 | 
				
			||||||
	if err := mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer mc.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if sql.IsolationLevel(opts.Isolation) != sql.LevelDefault {
 | 
					 | 
				
			||||||
		level, err := mapIsolationLevel(opts.Isolation)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		err = mc.exec("SET TRANSACTION ISOLATION LEVEL " + level)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mc.begin(opts.ReadOnly)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
 | 
					 | 
				
			||||||
	dargs, err := namedValueToValue(args)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rows, err := mc.query(query, dargs)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		mc.finish()
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rows.finish = mc.finish
 | 
					 | 
				
			||||||
	return rows, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
 | 
					 | 
				
			||||||
	dargs, err := namedValueToValue(args)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer mc.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mc.Exec(query, dargs)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
 | 
					 | 
				
			||||||
	if err := mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stmt, err := mc.Prepare(query)
 | 
					 | 
				
			||||||
	mc.finish()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
	case <-ctx.Done():
 | 
					 | 
				
			||||||
		stmt.Close()
 | 
					 | 
				
			||||||
		return nil, ctx.Err()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return stmt, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (stmt *mysqlStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
 | 
					 | 
				
			||||||
	dargs, err := namedValueToValue(args)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := stmt.mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rows, err := stmt.query(dargs)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		stmt.mc.finish()
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rows.finish = stmt.mc.finish
 | 
					 | 
				
			||||||
	return rows, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (stmt *mysqlStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
 | 
					 | 
				
			||||||
	dargs, err := namedValueToValue(args)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := stmt.mc.watchCancel(ctx); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer stmt.mc.finish()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return stmt.Exec(dargs)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) watchCancel(ctx context.Context) error {
 | 
					 | 
				
			||||||
	if mc.watching {
 | 
					 | 
				
			||||||
		// Reach here if canceled,
 | 
					 | 
				
			||||||
		// so the connection is already invalid
 | 
					 | 
				
			||||||
		mc.cleanup()
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if ctx.Done() == nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mc.watching = true
 | 
					 | 
				
			||||||
	select {
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
	case <-ctx.Done():
 | 
					 | 
				
			||||||
		return ctx.Err()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if mc.watcher == nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mc.watcher <- ctx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) startWatcher() {
 | 
					 | 
				
			||||||
	watcher := make(chan mysqlContext, 1)
 | 
					 | 
				
			||||||
	mc.watcher = watcher
 | 
					 | 
				
			||||||
	finished := make(chan struct{})
 | 
					 | 
				
			||||||
	mc.finished = finished
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		for {
 | 
					 | 
				
			||||||
			var ctx mysqlContext
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case ctx = <-watcher:
 | 
					 | 
				
			||||||
			case <-mc.closech:
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case <-ctx.Done():
 | 
					 | 
				
			||||||
				mc.cancel(ctx.Err())
 | 
					 | 
				
			||||||
			case <-finished:
 | 
					 | 
				
			||||||
			case <-mc.closech:
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
 | 
					 | 
				
			||||||
	nv.Value, err = converter{}.ConvertValue(nv.Value)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ResetSession implements driver.SessionResetter.
 | 
					 | 
				
			||||||
// (From Go 1.10)
 | 
					 | 
				
			||||||
func (mc *mysqlConn) ResetSession(ctx context.Context) error {
 | 
					 | 
				
			||||||
	if mc.closed.IsSet() {
 | 
					 | 
				
			||||||
		return driver.ErrBadConn
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										24
									
								
								vendor/github.com/go-sql-driver/mysql/driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								vendor/github.com/go-sql-driver/mysql/driver.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -23,11 +23,6 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// watcher interface is used for context support (From Go 1.8)
 | 
					 | 
				
			||||||
type watcher interface {
 | 
					 | 
				
			||||||
	startWatcher()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// MySQLDriver is exported to make the driver directly accessible.
 | 
					// MySQLDriver is exported to make the driver directly accessible.
 | 
				
			||||||
// In general the driver is used via the database/sql package.
 | 
					// In general the driver is used via the database/sql package.
 | 
				
			||||||
type MySQLDriver struct{}
 | 
					type MySQLDriver struct{}
 | 
				
			||||||
@ -55,7 +50,7 @@ func RegisterDial(net string, dial DialFunc) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Open new Connection.
 | 
					// Open new Connection.
 | 
				
			||||||
// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
 | 
					// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
 | 
				
			||||||
// the DSN string is formated
 | 
					// the DSN string is formatted
 | 
				
			||||||
func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 | 
					func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -82,6 +77,10 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 | 
				
			|||||||
		mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr)
 | 
							mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
 | 
				
			||||||
 | 
								errLog.Print("net.Error from Dial()': ", nerr.Error())
 | 
				
			||||||
 | 
								return nil, driver.ErrBadConn
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,9 +95,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Call startWatcher for context support (From Go 1.8)
 | 
						// Call startWatcher for context support (From Go 1.8)
 | 
				
			||||||
	if s, ok := interface{}(mc).(watcher); ok {
 | 
						mc.startWatcher()
 | 
				
			||||||
		s.startWatcher()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mc.buf = newBuffer(mc.netConn)
 | 
						mc.buf = newBuffer(mc.netConn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,20 +109,23 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 | 
				
			|||||||
		mc.cleanup()
 | 
							mc.cleanup()
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if plugin == "" {
 | 
				
			||||||
 | 
							plugin = defaultAuthPlugin
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send Client Authentication Packet
 | 
						// Send Client Authentication Packet
 | 
				
			||||||
	authResp, addNUL, err := mc.auth(authData, plugin)
 | 
						authResp, err := mc.auth(authData, plugin)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// try the default auth plugin, if using the requested plugin failed
 | 
							// try the default auth plugin, if using the requested plugin failed
 | 
				
			||||||
		errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
 | 
							errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
 | 
				
			||||||
		plugin = defaultAuthPlugin
 | 
							plugin = defaultAuthPlugin
 | 
				
			||||||
		authResp, addNUL, err = mc.auth(authData, plugin)
 | 
							authResp, err = mc.auth(authData, plugin)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			mc.cleanup()
 | 
								mc.cleanup()
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
 | 
						if err = mc.writeHandshakeResponsePacket(authResp, plugin); err != nil {
 | 
				
			||||||
		mc.cleanup()
 | 
							mc.cleanup()
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vendor/github.com/go-sql-driver/mysql/dsn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/go-sql-driver/mysql/dsn.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -560,7 +560,7 @@ func parseDSNParams(cfg *Config, params string) (err error) {
 | 
				
			|||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					cfg.TLSConfig = "false"
 | 
										cfg.TLSConfig = "false"
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else if vl := strings.ToLower(value); vl == "skip-verify" {
 | 
								} else if vl := strings.ToLower(value); vl == "skip-verify" || vl == "preferred" {
 | 
				
			||||||
				cfg.TLSConfig = vl
 | 
									cfg.TLSConfig = vl
 | 
				
			||||||
				cfg.tls = &tls.Config{InsecureSkipVerify: true}
 | 
									cfg.tls = &tls.Config{InsecureSkipVerify: true}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										99
									
								
								vendor/github.com/go-sql-driver/mysql/packets.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										99
									
								
								vendor/github.com/go-sql-driver/mysql/packets.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -51,7 +51,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
 | 
				
			|||||||
		mc.sequence++
 | 
							mc.sequence++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// packets with length 0 terminate a previous packet which is a
 | 
							// 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 {
 | 
							if pktLen == 0 {
 | 
				
			||||||
			// there was no previous packet
 | 
								// there was no previous packet
 | 
				
			||||||
			if prevData == nil {
 | 
								if prevData == nil {
 | 
				
			||||||
@ -154,15 +154,15 @@ func (mc *mysqlConn) writePacket(data []byte) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Handshake Initialization Packet
 | 
					// Handshake Initialization Packet
 | 
				
			||||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
 | 
					// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
 | 
				
			||||||
func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
 | 
					func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
 | 
				
			||||||
	data, err := mc.readPacket()
 | 
						data, err = mc.readPacket()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
 | 
							// 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.
 | 
							// in connection initialization we don't risk retrying non-idempotent actions.
 | 
				
			||||||
		if err == ErrInvalidConn {
 | 
							if err == ErrInvalidConn {
 | 
				
			||||||
			return nil, "", driver.ErrBadConn
 | 
								return nil, "", driver.ErrBadConn
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, "", err
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if data[0] == iERR {
 | 
						if data[0] == iERR {
 | 
				
			||||||
@ -194,11 +194,14 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
 | 
				
			|||||||
		return nil, "", ErrOldProtocol
 | 
							return nil, "", ErrOldProtocol
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
 | 
						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
 | 
						pos += 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	plugin := ""
 | 
					 | 
				
			||||||
	if len(data) > pos {
 | 
						if len(data) > pos {
 | 
				
			||||||
		// character set [1 byte]
 | 
							// character set [1 byte]
 | 
				
			||||||
		// status flags [2 bytes]
 | 
							// status flags [2 bytes]
 | 
				
			||||||
@ -236,8 +239,6 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
 | 
				
			|||||||
		return b[:], plugin, nil
 | 
							return b[:], plugin, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	plugin = defaultAuthPlugin
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// make a memory safe copy of the cipher slice
 | 
						// make a memory safe copy of the cipher slice
 | 
				
			||||||
	var b [8]byte
 | 
						var b [8]byte
 | 
				
			||||||
	copy(b[:], authData)
 | 
						copy(b[:], authData)
 | 
				
			||||||
@ -246,7 +247,7 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Client Authentication Packet
 | 
					// Client Authentication Packet
 | 
				
			||||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
 | 
					// 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
 | 
						// Adjust client flags based on server support
 | 
				
			||||||
	clientFlags := clientProtocol41 |
 | 
						clientFlags := clientProtocol41 |
 | 
				
			||||||
		clientSecureConn |
 | 
							clientSecureConn |
 | 
				
			||||||
@ -272,7 +273,8 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// encode length of the auth plugin data
 | 
						// encode length of the auth plugin data
 | 
				
			||||||
	var authRespLEIBuf [9]byte
 | 
						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 len(authRespLEI) > 1 {
 | 
				
			||||||
		// if the length can not be written in 1 byte, it must be written as a
 | 
							// if the length can not be written in 1 byte, it must be written as a
 | 
				
			||||||
		// length encoded integer
 | 
							// length encoded integer
 | 
				
			||||||
@ -280,9 +282,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
 | 
						pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
 | 
				
			||||||
	if addNUL {
 | 
					 | 
				
			||||||
		pktLen++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// To specify a db name
 | 
						// To specify a db name
 | 
				
			||||||
	if n := len(mc.cfg.DBName); n > 0 {
 | 
						if n := len(mc.cfg.DBName); n > 0 {
 | 
				
			||||||
@ -291,10 +290,10 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Calculate packet length and get buffer with that size
 | 
						// Calculate packet length and get buffer with that size
 | 
				
			||||||
	data := mc.buf.takeSmallBuffer(pktLen + 4)
 | 
						data, err := mc.buf.takeSmallBuffer(pktLen + 4)
 | 
				
			||||||
	if data == nil {
 | 
						if err != nil {
 | 
				
			||||||
		// cannot take the buffer. Something must be wrong with the connection
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -353,10 +352,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
 | 
				
			|||||||
	// Auth Data [length encoded integer]
 | 
						// Auth Data [length encoded integer]
 | 
				
			||||||
	pos += copy(data[pos:], authRespLEI)
 | 
						pos += copy(data[pos:], authRespLEI)
 | 
				
			||||||
	pos += copy(data[pos:], authResp)
 | 
						pos += copy(data[pos:], authResp)
 | 
				
			||||||
	if addNUL {
 | 
					 | 
				
			||||||
		data[pos] = 0x00
 | 
					 | 
				
			||||||
		pos++
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Databasename [null terminated string]
 | 
						// Databasename [null terminated string]
 | 
				
			||||||
	if len(mc.cfg.DBName) > 0 {
 | 
						if len(mc.cfg.DBName) > 0 {
 | 
				
			||||||
@ -367,30 +362,24 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pos += copy(data[pos:], plugin)
 | 
						pos += copy(data[pos:], plugin)
 | 
				
			||||||
	data[pos] = 0x00
 | 
						data[pos] = 0x00
 | 
				
			||||||
 | 
						pos++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send Auth packet
 | 
						// 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
 | 
					// 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)
 | 
						pktLen := 4 + len(authData)
 | 
				
			||||||
	if addNUL {
 | 
						data, err := mc.buf.takeSmallBuffer(pktLen)
 | 
				
			||||||
		pktLen++
 | 
						if err != nil {
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	data := mc.buf.takeSmallBuffer(pktLen)
 | 
					 | 
				
			||||||
	if data == nil {
 | 
					 | 
				
			||||||
		// cannot take the buffer. Something must be wrong with the connection
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add the auth data [EOF]
 | 
						// Add the auth data [EOF]
 | 
				
			||||||
	copy(data[4:], authData)
 | 
						copy(data[4:], authData)
 | 
				
			||||||
	if addNUL {
 | 
					 | 
				
			||||||
		data[pktLen-1] = 0x00
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mc.writePacket(data)
 | 
						return mc.writePacket(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -402,10 +391,10 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
 | 
				
			|||||||
	// Reset Packet Sequence
 | 
						// Reset Packet Sequence
 | 
				
			||||||
	mc.sequence = 0
 | 
						mc.sequence = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data := mc.buf.takeSmallBuffer(4 + 1)
 | 
						data, err := mc.buf.takeSmallBuffer(4 + 1)
 | 
				
			||||||
	if data == nil {
 | 
						if err != nil {
 | 
				
			||||||
		// cannot take the buffer. Something must be wrong with the connection
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -421,10 +410,10 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
 | 
				
			|||||||
	mc.sequence = 0
 | 
						mc.sequence = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pktLen := 1 + len(arg)
 | 
						pktLen := 1 + len(arg)
 | 
				
			||||||
	data := mc.buf.takeBuffer(pktLen + 4)
 | 
						data, err := mc.buf.takeBuffer(pktLen + 4)
 | 
				
			||||||
	if data == nil {
 | 
						if err != nil {
 | 
				
			||||||
		// cannot take the buffer. Something must be wrong with the connection
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -442,10 +431,10 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
 | 
				
			|||||||
	// Reset Packet Sequence
 | 
						// Reset Packet Sequence
 | 
				
			||||||
	mc.sequence = 0
 | 
						mc.sequence = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data := mc.buf.takeSmallBuffer(4 + 1 + 4)
 | 
						data, err := mc.buf.takeSmallBuffer(4 + 1 + 4)
 | 
				
			||||||
	if data == nil {
 | 
						if err != nil {
 | 
				
			||||||
		// cannot take the buffer. Something must be wrong with the connection
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -482,7 +471,7 @@ func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
 | 
				
			|||||||
		return data[1:], "", err
 | 
							return data[1:], "", err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case iEOF:
 | 
						case iEOF:
 | 
				
			||||||
		if len(data) < 1 {
 | 
							if len(data) == 1 {
 | 
				
			||||||
			// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
 | 
								// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
 | 
				
			||||||
			return nil, "mysql_old_password", nil
 | 
								return nil, "mysql_old_password", nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -898,7 +887,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 | 
				
			|||||||
	const minPktLen = 4 + 1 + 4 + 1 + 4
 | 
						const minPktLen = 4 + 1 + 4 + 1 + 4
 | 
				
			||||||
	mc := stmt.mc
 | 
						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)
 | 
						longDataSize := mc.maxAllowedPacket / (stmt.paramCount + 1)
 | 
				
			||||||
	if longDataSize < 64 {
 | 
						if longDataSize < 64 {
 | 
				
			||||||
		longDataSize = 64
 | 
							longDataSize = 64
 | 
				
			||||||
@ -908,15 +897,17 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 | 
				
			|||||||
	mc.sequence = 0
 | 
						mc.sequence = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var data []byte
 | 
						var data []byte
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(args) == 0 {
 | 
						if len(args) == 0 {
 | 
				
			||||||
		data = mc.buf.takeBuffer(minPktLen)
 | 
							data, err = mc.buf.takeBuffer(minPktLen)
 | 
				
			||||||
	} else {
 | 
						} 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
 | 
							// cannot take the buffer. Something must be wrong with the connection
 | 
				
			||||||
		errLog.Print(ErrBusyBuffer)
 | 
							errLog.Print(err)
 | 
				
			||||||
		return errBadConnNoWrite
 | 
							return errBadConnNoWrite
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -942,7 +933,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 | 
				
			|||||||
		pos := minPktLen
 | 
							pos := minPktLen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var nullMask []byte
 | 
							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
 | 
								// 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 depend on append after all data with known sizes fit.
 | 
				
			||||||
			// We stop at that because we deal with a lot of columns here
 | 
								// We stop at that because we deal with a lot of columns here
 | 
				
			||||||
@ -951,10 +942,11 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 | 
				
			|||||||
			copy(tmp[:pos], data[:pos])
 | 
								copy(tmp[:pos], data[:pos])
 | 
				
			||||||
			data = tmp
 | 
								data = tmp
 | 
				
			||||||
			nullMask = data[pos : pos+maskLen]
 | 
								nullMask = data[pos : pos+maskLen]
 | 
				
			||||||
 | 
								// No need to clean nullMask as make ensures that.
 | 
				
			||||||
			pos += maskLen
 | 
								pos += maskLen
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			nullMask = data[pos : pos+maskLen]
 | 
								nullMask = data[pos : pos+maskLen]
 | 
				
			||||||
			for i := 0; i < maskLen; i++ {
 | 
								for i := range nullMask {
 | 
				
			||||||
				nullMask[i] = 0
 | 
									nullMask[i] = 0
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			pos += maskLen
 | 
								pos += maskLen
 | 
				
			||||||
@ -1091,7 +1083,10 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 | 
				
			|||||||
		// In that case we must build the data packet with the new values buffer
 | 
							// In that case we must build the data packet with the new values buffer
 | 
				
			||||||
		if valuesCap != cap(paramValues) {
 | 
							if valuesCap != cap(paramValues) {
 | 
				
			||||||
			data = append(data[:pos], 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)
 | 
							pos += len(paramValues)
 | 
				
			||||||
@ -1261,7 +1256,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 | 
				
			|||||||
						rows.rs.columns[i].decimals,
 | 
											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:
 | 
								case rows.mc.parseTime:
 | 
				
			||||||
				dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
 | 
									dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
@ -1281,7 +1276,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 {
 | 
								if err == nil {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										277
									
								
								vendor/github.com/go-sql-driver/mysql/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										277
									
								
								vendor/github.com/go-sql-driver/mysql/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -10,10 +10,13 @@ package mysql
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"database/sql"
 | 
				
			||||||
	"database/sql/driver"
 | 
						"database/sql/driver"
 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"sync/atomic"
 | 
						"sync/atomic"
 | 
				
			||||||
@ -79,7 +82,7 @@ func DeregisterTLSConfig(key string) {
 | 
				
			|||||||
func getTLSConfigClone(key string) (config *tls.Config) {
 | 
					func getTLSConfigClone(key string) (config *tls.Config) {
 | 
				
			||||||
	tlsConfigLock.RLock()
 | 
						tlsConfigLock.RLock()
 | 
				
			||||||
	if v, ok := tlsConfigRegistry[key]; ok {
 | 
						if v, ok := tlsConfigRegistry[key]; ok {
 | 
				
			||||||
		config = cloneTLSConfig(v)
 | 
							config = v.Clone()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tlsConfigLock.RUnlock()
 | 
						tlsConfigLock.RUnlock()
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
@ -227,87 +230,104 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
 | 
				
			|||||||
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
 | 
					const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
 | 
				
			||||||
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
 | 
					const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) {
 | 
					func appendMicrosecs(dst, src []byte, decimals int) []byte {
 | 
				
			||||||
 | 
						if decimals <= 0 {
 | 
				
			||||||
 | 
							return dst
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(src) == 0 {
 | 
				
			||||||
 | 
							return append(dst, ".000000"[:decimals+1]...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						microsecs := binary.LittleEndian.Uint32(src[:4])
 | 
				
			||||||
 | 
						p1 := byte(microsecs / 10000)
 | 
				
			||||||
 | 
						microsecs -= 10000 * uint32(p1)
 | 
				
			||||||
 | 
						p2 := byte(microsecs / 100)
 | 
				
			||||||
 | 
						microsecs -= 100 * uint32(p2)
 | 
				
			||||||
 | 
						p3 := byte(microsecs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch decimals {
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1], digits01[p1],
 | 
				
			||||||
 | 
								digits10[p2], digits01[p2],
 | 
				
			||||||
 | 
								digits10[p3], digits01[p3],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1], digits01[p1],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1], digits01[p1],
 | 
				
			||||||
 | 
								digits10[p2],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1], digits01[p1],
 | 
				
			||||||
 | 
								digits10[p2], digits01[p2],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						case 5:
 | 
				
			||||||
 | 
							return append(dst, '.',
 | 
				
			||||||
 | 
								digits10[p1], digits01[p1],
 | 
				
			||||||
 | 
								digits10[p2], digits01[p2],
 | 
				
			||||||
 | 
								digits10[p3],
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func formatBinaryDateTime(src []byte, length uint8) (driver.Value, error) {
 | 
				
			||||||
	// length expects the deterministic length of the zero value,
 | 
						// length expects the deterministic length of the zero value,
 | 
				
			||||||
	// negative time and 100+ hours are automatically added if needed
 | 
						// negative time and 100+ hours are automatically added if needed
 | 
				
			||||||
	if len(src) == 0 {
 | 
						if len(src) == 0 {
 | 
				
			||||||
		if justTime {
 | 
					 | 
				
			||||||
			return zeroDateTime[11 : 11+length], nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return zeroDateTime[:length], nil
 | 
							return zeroDateTime[:length], nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var dst []byte          // return value
 | 
						var dst []byte      // return value
 | 
				
			||||||
	var pt, p1, p2, p3 byte // current digit pair
 | 
						var p1, p2, p3 byte // current digit pair
 | 
				
			||||||
	var zOffs byte          // offset of value in zeroDateTime
 | 
					
 | 
				
			||||||
	if justTime {
 | 
						switch length {
 | 
				
			||||||
		switch length {
 | 
						case 10, 19, 21, 22, 23, 24, 25, 26:
 | 
				
			||||||
		case
 | 
						default:
 | 
				
			||||||
			8,                      // time (can be up to 10 when negative and 100+ hours)
 | 
							t := "DATE"
 | 
				
			||||||
			10, 11, 12, 13, 14, 15: // time with fractional seconds
 | 
							if length > 10 {
 | 
				
			||||||
		default:
 | 
								t += "TIME"
 | 
				
			||||||
			return nil, fmt.Errorf("illegal TIME length %d", length)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		switch len(src) {
 | 
							return nil, fmt.Errorf("illegal %s length %d", t, length)
 | 
				
			||||||
		case 8, 12:
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// +2 to enable negative time and 100+ hours
 | 
					 | 
				
			||||||
		dst = make([]byte, 0, length+2)
 | 
					 | 
				
			||||||
		if src[0] == 1 {
 | 
					 | 
				
			||||||
			dst = append(dst, '-')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if src[1] != 0 {
 | 
					 | 
				
			||||||
			hour := uint16(src[1])*24 + uint16(src[5])
 | 
					 | 
				
			||||||
			pt = byte(hour / 100)
 | 
					 | 
				
			||||||
			p1 = byte(hour - 100*uint16(pt))
 | 
					 | 
				
			||||||
			dst = append(dst, digits01[pt])
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			p1 = src[5]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		zOffs = 11
 | 
					 | 
				
			||||||
		src = src[6:]
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		switch length {
 | 
					 | 
				
			||||||
		case 10, 19, 21, 22, 23, 24, 25, 26:
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			t := "DATE"
 | 
					 | 
				
			||||||
			if length > 10 {
 | 
					 | 
				
			||||||
				t += "TIME"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("illegal %s length %d", t, length)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch len(src) {
 | 
					 | 
				
			||||||
		case 4, 7, 11:
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			t := "DATE"
 | 
					 | 
				
			||||||
			if length > 10 {
 | 
					 | 
				
			||||||
				t += "TIME"
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dst = make([]byte, 0, length)
 | 
					 | 
				
			||||||
		// start with the date
 | 
					 | 
				
			||||||
		year := binary.LittleEndian.Uint16(src[:2])
 | 
					 | 
				
			||||||
		pt = byte(year / 100)
 | 
					 | 
				
			||||||
		p1 = byte(year - 100*uint16(pt))
 | 
					 | 
				
			||||||
		p2, p3 = src[2], src[3]
 | 
					 | 
				
			||||||
		dst = append(dst,
 | 
					 | 
				
			||||||
			digits10[pt], digits01[pt],
 | 
					 | 
				
			||||||
			digits10[p1], digits01[p1], '-',
 | 
					 | 
				
			||||||
			digits10[p2], digits01[p2], '-',
 | 
					 | 
				
			||||||
			digits10[p3], digits01[p3],
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		if length == 10 {
 | 
					 | 
				
			||||||
			return dst, nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if len(src) == 4 {
 | 
					 | 
				
			||||||
			return append(dst, zeroDateTime[10:length]...), nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dst = append(dst, ' ')
 | 
					 | 
				
			||||||
		p1 = src[4] // hour
 | 
					 | 
				
			||||||
		src = src[5:]
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						switch len(src) {
 | 
				
			||||||
 | 
						case 4, 7, 11:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							t := "DATE"
 | 
				
			||||||
 | 
							if length > 10 {
 | 
				
			||||||
 | 
								t += "TIME"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dst = make([]byte, 0, length)
 | 
				
			||||||
 | 
						// start with the date
 | 
				
			||||||
 | 
						year := binary.LittleEndian.Uint16(src[:2])
 | 
				
			||||||
 | 
						pt := year / 100
 | 
				
			||||||
 | 
						p1 = byte(year - 100*uint16(pt))
 | 
				
			||||||
 | 
						p2, p3 = src[2], src[3]
 | 
				
			||||||
 | 
						dst = append(dst,
 | 
				
			||||||
 | 
							digits10[pt], digits01[pt],
 | 
				
			||||||
 | 
							digits10[p1], digits01[p1], '-',
 | 
				
			||||||
 | 
							digits10[p2], digits01[p2], '-',
 | 
				
			||||||
 | 
							digits10[p3], digits01[p3],
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if length == 10 {
 | 
				
			||||||
 | 
							return dst, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(src) == 4 {
 | 
				
			||||||
 | 
							return append(dst, zeroDateTime[10:length]...), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dst = append(dst, ' ')
 | 
				
			||||||
 | 
						p1 = src[4] // hour
 | 
				
			||||||
 | 
						src = src[5:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// p1 is 2-digit hour, src is after hour
 | 
						// p1 is 2-digit hour, src is after hour
 | 
				
			||||||
	p2, p3 = src[0], src[1]
 | 
						p2, p3 = src[0], src[1]
 | 
				
			||||||
	dst = append(dst,
 | 
						dst = append(dst,
 | 
				
			||||||
@ -315,51 +335,49 @@ func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value
 | 
				
			|||||||
		digits10[p2], digits01[p2], ':',
 | 
							digits10[p2], digits01[p2], ':',
 | 
				
			||||||
		digits10[p3], digits01[p3],
 | 
							digits10[p3], digits01[p3],
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if length <= byte(len(dst)) {
 | 
						return appendMicrosecs(dst, src[2:], int(length)-20), nil
 | 
				
			||||||
		return dst, nil
 | 
					}
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	src = src[2:]
 | 
					func formatBinaryTime(src []byte, length uint8) (driver.Value, error) {
 | 
				
			||||||
 | 
						// length expects the deterministic length of the zero value,
 | 
				
			||||||
 | 
						// negative time and 100+ hours are automatically added if needed
 | 
				
			||||||
	if len(src) == 0 {
 | 
						if len(src) == 0 {
 | 
				
			||||||
		return append(dst, zeroDateTime[19:zOffs+length]...), nil
 | 
							return zeroDateTime[11 : 11+length], nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	microsecs := binary.LittleEndian.Uint32(src[:4])
 | 
						var dst []byte // return value
 | 
				
			||||||
	p1 = byte(microsecs / 10000)
 | 
					
 | 
				
			||||||
	microsecs -= 10000 * uint32(p1)
 | 
						switch length {
 | 
				
			||||||
	p2 = byte(microsecs / 100)
 | 
						case
 | 
				
			||||||
	microsecs -= 100 * uint32(p2)
 | 
							8,                      // time (can be up to 10 when negative and 100+ hours)
 | 
				
			||||||
	p3 = byte(microsecs)
 | 
							10, 11, 12, 13, 14, 15: // time with fractional seconds
 | 
				
			||||||
	switch decimals := zOffs + length - 20; decimals {
 | 
					 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return append(dst, '.',
 | 
							return nil, fmt.Errorf("illegal TIME length %d", length)
 | 
				
			||||||
			digits10[p1], digits01[p1],
 | 
					 | 
				
			||||||
			digits10[p2], digits01[p2],
 | 
					 | 
				
			||||||
			digits10[p3], digits01[p3],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	case 1:
 | 
					 | 
				
			||||||
		return append(dst, '.',
 | 
					 | 
				
			||||||
			digits10[p1],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	case 2:
 | 
					 | 
				
			||||||
		return append(dst, '.',
 | 
					 | 
				
			||||||
			digits10[p1], digits01[p1],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	case 3:
 | 
					 | 
				
			||||||
		return append(dst, '.',
 | 
					 | 
				
			||||||
			digits10[p1], digits01[p1],
 | 
					 | 
				
			||||||
			digits10[p2],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	case 4:
 | 
					 | 
				
			||||||
		return append(dst, '.',
 | 
					 | 
				
			||||||
			digits10[p1], digits01[p1],
 | 
					 | 
				
			||||||
			digits10[p2], digits01[p2],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	case 5:
 | 
					 | 
				
			||||||
		return append(dst, '.',
 | 
					 | 
				
			||||||
			digits10[p1], digits01[p1],
 | 
					 | 
				
			||||||
			digits10[p2], digits01[p2],
 | 
					 | 
				
			||||||
			digits10[p3],
 | 
					 | 
				
			||||||
		), nil
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						switch len(src) {
 | 
				
			||||||
 | 
						case 8, 12:
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// +2 to enable negative time and 100+ hours
 | 
				
			||||||
 | 
						dst = make([]byte, 0, length+2)
 | 
				
			||||||
 | 
						if src[0] == 1 {
 | 
				
			||||||
 | 
							dst = append(dst, '-')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						days := binary.LittleEndian.Uint32(src[1:5])
 | 
				
			||||||
 | 
						hours := int64(days)*24 + int64(src[5])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if hours >= 100 {
 | 
				
			||||||
 | 
							dst = strconv.AppendInt(dst, hours, 10)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							dst = append(dst, digits10[hours], digits01[hours])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						min, sec := src[6], src[7]
 | 
				
			||||||
 | 
						dst = append(dst, ':',
 | 
				
			||||||
 | 
							digits10[min], digits01[min], ':',
 | 
				
			||||||
 | 
							digits10[sec], digits01[sec],
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return appendMicrosecs(dst, src[8:], int(length)-9), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/******************************************************************************
 | 
					/******************************************************************************
 | 
				
			||||||
@ -708,3 +726,30 @@ func (ae *atomicError) Value() error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
 | 
				
			||||||
 | 
						dargs := make([]driver.Value, len(named))
 | 
				
			||||||
 | 
						for n, param := range named {
 | 
				
			||||||
 | 
							if len(param.Name) > 0 {
 | 
				
			||||||
 | 
								// TODO: support the use of Named Parameters #561
 | 
				
			||||||
 | 
								return nil, errors.New("mysql: driver does not support the use of Named Parameters")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							dargs[n] = param.Value
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return dargs, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
 | 
				
			||||||
 | 
						switch sql.IsolationLevel(level) {
 | 
				
			||||||
 | 
						case sql.LevelRepeatableRead:
 | 
				
			||||||
 | 
							return "REPEATABLE READ", nil
 | 
				
			||||||
 | 
						case sql.LevelReadCommitted:
 | 
				
			||||||
 | 
							return "READ COMMITTED", nil
 | 
				
			||||||
 | 
						case sql.LevelReadUncommitted:
 | 
				
			||||||
 | 
							return "READ UNCOMMITTED", nil
 | 
				
			||||||
 | 
						case sql.LevelSerializable:
 | 
				
			||||||
 | 
							return "SERIALIZABLE", nil
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								vendor/github.com/go-sql-driver/mysql/utils_go17.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/go-sql-driver/mysql/utils_go17.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -1,40 +0,0 @@
 | 
				
			|||||||
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This Source Code Form is subject to the terms of the Mozilla Public
 | 
					 | 
				
			||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
 | 
					 | 
				
			||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build go1.7
 | 
					 | 
				
			||||||
// +build !go1.8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mysql
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "crypto/tls"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cloneTLSConfig(c *tls.Config) *tls.Config {
 | 
					 | 
				
			||||||
	return &tls.Config{
 | 
					 | 
				
			||||||
		Rand:                        c.Rand,
 | 
					 | 
				
			||||||
		Time:                        c.Time,
 | 
					 | 
				
			||||||
		Certificates:                c.Certificates,
 | 
					 | 
				
			||||||
		NameToCertificate:           c.NameToCertificate,
 | 
					 | 
				
			||||||
		GetCertificate:              c.GetCertificate,
 | 
					 | 
				
			||||||
		RootCAs:                     c.RootCAs,
 | 
					 | 
				
			||||||
		NextProtos:                  c.NextProtos,
 | 
					 | 
				
			||||||
		ServerName:                  c.ServerName,
 | 
					 | 
				
			||||||
		ClientAuth:                  c.ClientAuth,
 | 
					 | 
				
			||||||
		ClientCAs:                   c.ClientCAs,
 | 
					 | 
				
			||||||
		InsecureSkipVerify:          c.InsecureSkipVerify,
 | 
					 | 
				
			||||||
		CipherSuites:                c.CipherSuites,
 | 
					 | 
				
			||||||
		PreferServerCipherSuites:    c.PreferServerCipherSuites,
 | 
					 | 
				
			||||||
		SessionTicketsDisabled:      c.SessionTicketsDisabled,
 | 
					 | 
				
			||||||
		SessionTicketKey:            c.SessionTicketKey,
 | 
					 | 
				
			||||||
		ClientSessionCache:          c.ClientSessionCache,
 | 
					 | 
				
			||||||
		MinVersion:                  c.MinVersion,
 | 
					 | 
				
			||||||
		MaxVersion:                  c.MaxVersion,
 | 
					 | 
				
			||||||
		CurvePreferences:            c.CurvePreferences,
 | 
					 | 
				
			||||||
		DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
 | 
					 | 
				
			||||||
		Renegotiation:               c.Renegotiation,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										50
									
								
								vendor/github.com/go-sql-driver/mysql/utils_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										50
									
								
								vendor/github.com/go-sql-driver/mysql/utils_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@ -1,50 +0,0 @@
 | 
				
			|||||||
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This Source Code Form is subject to the terms of the Mozilla Public
 | 
					 | 
				
			||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
 | 
					 | 
				
			||||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// +build go1.8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package mysql
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"crypto/tls"
 | 
					 | 
				
			||||||
	"database/sql"
 | 
					 | 
				
			||||||
	"database/sql/driver"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func cloneTLSConfig(c *tls.Config) *tls.Config {
 | 
					 | 
				
			||||||
	return c.Clone()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
 | 
					 | 
				
			||||||
	dargs := make([]driver.Value, len(named))
 | 
					 | 
				
			||||||
	for n, param := range named {
 | 
					 | 
				
			||||||
		if len(param.Name) > 0 {
 | 
					 | 
				
			||||||
			// TODO: support the use of Named Parameters #561
 | 
					 | 
				
			||||||
			return nil, errors.New("mysql: driver does not support the use of Named Parameters")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		dargs[n] = param.Value
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return dargs, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
 | 
					 | 
				
			||||||
	switch sql.IsolationLevel(level) {
 | 
					 | 
				
			||||||
	case sql.LevelRepeatableRead:
 | 
					 | 
				
			||||||
		return "REPEATABLE READ", nil
 | 
					 | 
				
			||||||
	case sql.LevelReadCommitted:
 | 
					 | 
				
			||||||
		return "READ COMMITTED", nil
 | 
					 | 
				
			||||||
	case sql.LevelReadUncommitted:
 | 
					 | 
				
			||||||
		return "READ UNCOMMITTED", nil
 | 
					 | 
				
			||||||
	case sql.LevelSerializable:
 | 
					 | 
				
			||||||
		return "SERIALIZABLE", nil
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user