upgrade go-sql-driver/mysql to fix invalid connection error (#5748)
should fix #5736tokarchuk/v1.17
parent
5ac6da3c41
commit
477a80f658
@ -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 |
|
||||||
} |
|
@ -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, |
|
||||||
} |
|
||||||
} |
|
@ -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…
Reference in new issue