diff options
| author | Niall Sheridan <nsheridan@gmail.com> | 2017-10-18 13:15:14 +0100 | 
|---|---|---|
| committer | Niall Sheridan <niall@intercom.io> | 2017-10-18 13:25:46 +0100 | 
| commit | 7b320119ba532fd409ec7dade7ad02011c309599 (patch) | |
| tree | a39860f35b55e6cc499f8f5bfa969138c5dd6b73 /vendor/github.com/go-sql-driver | |
| parent | 7c99874c7a3e7a89716f3ee0cdf696532e35ae35 (diff) | |
Update dependencies
Diffstat (limited to 'vendor/github.com/go-sql-driver')
18 files changed, 949 insertions, 272 deletions
diff --git a/vendor/github.com/go-sql-driver/mysql/AUTHORS b/vendor/github.com/go-sql-driver/mysql/AUTHORS index e47e542..ac36be9 100644 --- a/vendor/github.com/go-sql-driver/mysql/AUTHORS +++ b/vendor/github.com/go-sql-driver/mysql/AUTHORS @@ -12,38 +12,52 @@  # Individual Persons  Aaron Hopkins <go-sql-driver at die.net> +Achille Roussel <achille.roussel at gmail.com>  Arne Hormann <arnehormann at gmail.com> +Asta Xie <xiemengjun at gmail.com> +Bulat Gaifullin <gaifullinbf at gmail.com>  Carlos Nieto <jose.carlos at menteslibres.net>  Chris Moos <chris at tech9computers.com>  Daniel Nichter <nil at codenode.com>  Daniël van Eeden <git at myname.nl> +Dave Protasowski <dprotaso at gmail.com>  DisposaBoy <disposaboy at dby.me>  Egor Smolyakov <egorsmkv at gmail.com> +Evan Shaw <evan at vendhq.com>  Frederick Mayle <frederickmayle at gmail.com>  Gustavo Kristic <gkristic at gmail.com>  Hanno Braun <mail at hannobraun.com>  Henri Yandell <flamefew at gmail.com>  Hirotaka Yamamoto <ymmt2005 at gmail.com> +ICHINOSE Shogo <shogo82148 at gmail.com>  INADA Naoki <songofacandy at gmail.com>  Jacek Szwec <szwec.jacek at gmail.com>  James Harr <james.harr at gmail.com> +Jeff Hodges <jeff at somethingsimilar.com> +Jeffrey Charles <jeffreycharles at gmail.com>  Jian Zhen <zhenjl at gmail.com>  Joshua Prunier <joshua.prunier at gmail.com>  Julien Lefevre <julien.lefevr at gmail.com>  Julien Schmidt <go-sql-driver at julienschmidt.com> +Justin Nuß <nuss.justin at gmail.com>  Kamil Dziedzic <kamil at klecza.pl>  Kevin Malachowski <kevin at chowski.com>  Lennart Rudolph <lrudolph at hmc.edu>  Leonardo YongUk Kim <dalinaum at gmail.com> +Lion Yang <lion at aosc.xyz>  Luca Looz <luca.looz92 at gmail.com>  Lucas Liu <extrafliu at gmail.com>  Luke Scott <luke at webconnex.com> +Maciej Zimnoch <maciej.zimnoch@codilime.com>  Michael Woolnough <michael.woolnough at gmail.com>  Nicola Peduzzi <thenikso at gmail.com>  Olivier Mengué <dolmen at cpan.org> +oscarzhao <oscarzhaosl at gmail.com>  Paul Bonser <misterpib at gmail.com>  Peter Schultz <peter.schultz at classmarkets.com> +Rebecca Chin <rchin at pivotal.io>  Runrioter Wung <runrioter at gmail.com> +Shuode Li <elemount at qq.com>  Soroush Pour <me at soroushjp.com>  Stan Putrya <root.vagner at gmail.com>  Stanley Gunawan <gunawan.stanley at gmail.com> @@ -56,4 +70,6 @@ Zhenye Xie <xiezhenye at gmail.com>  Barracuda Networks, Inc.  Google Inc. +Keybase Inc. +Pivotal Inc.  Stripe Inc. diff --git a/vendor/github.com/go-sql-driver/mysql/README.md b/vendor/github.com/go-sql-driver/mysql/README.md index a060e3c..d24aaa0 100644 --- a/vendor/github.com/go-sql-driver/mysql/README.md +++ b/vendor/github.com/go-sql-driver/mysql/README.md @@ -16,6 +16,8 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac        * [Parameters](#parameters)        * [Examples](#examples)      * [Connection pool and timeouts](#connection-pool-and-timeouts) +    * [context.Context Support](#contextcontext-support) +    * [ColumnType Support](#columntype-support)      * [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support)      * [time.Time support](#timetime-support)      * [Unicode support](#unicode-support) @@ -38,7 +40,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac    * Optional placeholder interpolation  ## Requirements -  * Go 1.2 or higher +  * Go 1.5 or higher    * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+)  --------------------------------------- @@ -46,7 +48,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac  ## Installation  Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell:  ```bash -$ go get github.com/go-sql-driver/mysql +$ go get -u github.com/go-sql-driver/mysql  ```  Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`. @@ -100,7 +102,8 @@ See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which netw  In general you should use an Unix domain socket if available and TCP otherwise for best performance.  #### Address -For TCP and UDP networks, addresses have the form `host:port`. +For TCP and UDP networks, addresses have the form `host[:port]`. +If `port` is omitted, the default port will be used.  If `host` is a literal IPv6 address, it must be enclosed in square brackets.  The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form. @@ -137,9 +140,9 @@ Default:        false  ```  Type:           bool  Valid Values:   true, false -Default:        false +Default:        true  ``` -`allowNativePasswords=true` allows the usage of the mysql native password method. +`allowNativePasswords=false` disallows the usage of MySQL native password method.  ##### `allowOldPasswords` @@ -230,10 +233,10 @@ Please keep in mind, that param values must be [url.QueryEscape](https://golang.  ##### `maxAllowedPacket`  ```  Type:          decimal number -Default:       0 +Default:       4194304  ``` -Max packet size allowed in bytes. Use `maxAllowedPacket=0` to automatically fetch the `max_allowed_packet` variable from server. +Max packet size allowed in bytes. The default value is 4 MiB and should be adjusted to match the server settings. `maxAllowedPacket=0` can be used to automatically fetch the `max_allowed_packet` variable from server *on every connection*.  ##### `multiStatements` @@ -267,7 +270,7 @@ Default:        0  I/O read timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. -##### `strict` +##### `rejectReadOnly`  ```  Type:           bool @@ -275,11 +278,27 @@ Valid Values:   true, false  Default:        false  ``` -`strict=true` enables a driver-side strict mode in which MySQL warnings are treated as errors. This mode should not be used in production as it may lead to data corruption in certain situations. -A server-side strict mode, which is safe for production use, can be set via the [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html) system variable. +`rejectReadOnly=true` causes the driver to reject read-only connections. This +is for a possible race condition during an automatic failover, where the mysql +client gets connected to a read-only replica after the failover. + +Note that this should be a fairly rare case, as an automatic failover normally +happens when the primary is down, and the race condition shouldn't happen +unless it comes back up online as soon as the failover is kicked off. On the +other hand, when this happens, a MySQL application can get stuck on a +read-only connection until restarted. It is however fairly easy to reproduce, +for example, using a manual failover on AWS Aurora's MySQL-compatible cluster. + +If you are not relying on read-only transactions to reject writes that aren't +supposed to happen, setting this on some MySQL providers (such as AWS Aurora) +is safer for failovers. + +Note that ERROR 1290 can be returned for a `read-only` server and this option will +cause a retry for that error. However the same error number is used for some +other cases. You should ensure your application will never cause an ERROR 1290 +except for `read-only` mode when enabling this option. -By default MySQL also treats notes as warnings. Use [`sql_notes=false`](http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sql_notes) to ignore notes.  ##### `timeout` @@ -290,6 +309,7 @@ Default:        OS default  Timeout for establishing connections, aka dial timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. +  ##### `tls`  ``` @@ -300,6 +320,7 @@ Default:        false  `tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). +  ##### `writeTimeout`  ``` @@ -318,9 +339,9 @@ Any other parameters are interpreted as system variables:    * `<string_var>=%27<value>%27`: `SET <string_var>='<value>'`  Rules: -* The values for string variables must be quoted with ' +* The values for string variables must be quoted with `'`.  * The values must also be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed! - (which implies values of string variables must be wrapped with `%27`) + (which implies values of string variables must be wrapped with `%27`).  Examples:    * `autocommit=1`: `SET autocommit=1` @@ -385,6 +406,13 @@ user:password@/  ### Connection pool and timeouts  The connection pool is managed by Go's database/sql package. For details on how to configure the size of the pool and how long connections stay in the pool see `*DB.SetMaxOpenConns`, `*DB.SetMaxIdleConns`, and `*DB.SetConnMaxLifetime` in the [database/sql documentation](https://golang.org/pkg/database/sql/). The read, write, and dial timeouts for each individual connection are configured with the DSN parameters [`readTimeout`](#readtimeout), [`writeTimeout`](#writetimeout), and [`timeout`](#timeout), respectively. +## `ColumnType` Support +This driver supports the [`ColumnType` interface](https://golang.org/pkg/database/sql/#ColumnType) introduced in Go 1.8, with the exception of [`ColumnType.Length()`](https://golang.org/pkg/database/sql/#ColumnType.Length), which is currently not supported. + +## `context.Context` Support +Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts. +See [context support in the database/sql package](https://golang.org/doc/go1.8#database_sql) for more details. +  ### `LOAD DATA LOCAL INFILE` support  For this feature you need direct access to the package. Therefore you must change the import path (no `_`): @@ -400,7 +428,7 @@ See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/my  ### `time.Time` support -The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your programm. +The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your program.  However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` variables, which is the logical opposite in Go to `DATE` and `DATETIME` in MySQL. You can do that by changing the internal output type from `[]byte` to `time.Time` with the DSN parameter `parseTime=true`. You can set the default [`time.Time` location](https://golang.org/pkg/time/#Location) with the `loc` DSN parameter. @@ -418,7 +446,6 @@ Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAM  See http://dev.mysql.com/doc/refman/5.7/en/charset-unicode.html for more details on MySQL's Unicode support. -  ## Testing / Development  To run the driver tests you may need to adjust the configuration. See the [Testing Wiki-Page](https://github.com/go-sql-driver/mysql/wiki/Testing "Testing") for details. @@ -437,13 +464,13 @@ Mozilla summarizes the license scope as follows:  That means: -  * You can **use** the **unchanged** source code both in private and commercially -  * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0) -  * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged** +  * You can **use** the **unchanged** source code both in private and commercially. +  * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0). +  * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**.  Please read the [MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you have further questions regarding the license. -You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE) +You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE).   diff --git a/vendor/github.com/go-sql-driver/mysql/connection.go b/vendor/github.com/go-sql-driver/mysql/connection.go index 08e5fad..e570614 100644 --- a/vendor/github.com/go-sql-driver/mysql/connection.go +++ b/vendor/github.com/go-sql-driver/mysql/connection.go @@ -17,6 +17,16 @@ import (  	"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 {  	buf              buffer  	netConn          net.Conn @@ -30,7 +40,14 @@ type mysqlConn struct {  	status           statusFlag  	sequence         uint8  	parseTime        bool -	strict           bool + +	// for context support (Go 1.8+) +	watching bool +	watcher  chan<- mysqlContext +	closech  chan struct{} +	finished chan<- struct{} +	canceled atomicError // set non-nil if conn is canceled +	closed   atomicBool  // set when conn is closed, before closech is closed  }  // Handles parameters set in DSN after the connection is established @@ -63,22 +80,41 @@ func (mc *mysqlConn) handleParams() (err error) {  	return  } +func (mc *mysqlConn) markBadConn(err error) error { +	if mc == nil { +		return err +	} +	if err != errBadConnNoWrite { +		return err +	} +	return driver.ErrBadConn +} +  func (mc *mysqlConn) Begin() (driver.Tx, error) { -	if mc.netConn == nil { +	return mc.begin(false) +} + +func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) { +	if mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	} -	err := mc.exec("START TRANSACTION") +	var q string +	if readOnly { +		q = "START TRANSACTION READ ONLY" +	} else { +		q = "START TRANSACTION" +	} +	err := mc.exec(q)  	if err == nil {  		return &mysqlTx{mc}, err  	} - -	return nil, err +	return nil, mc.markBadConn(err)  }  func (mc *mysqlConn) Close() (err error) {  	// Makes Close idempotent -	if mc.netConn != nil { +	if !mc.closed.IsSet() {  		err = mc.writeCommandPacket(comQuit)  	} @@ -92,26 +128,39 @@ func (mc *mysqlConn) Close() (err error) {  // is called before auth or on auth failure because MySQL will have already  // closed the network connection.  func (mc *mysqlConn) cleanup() { +	if !mc.closed.TrySet(true) { +		return +	} +  	// Makes cleanup idempotent -	if mc.netConn != nil { -		if err := mc.netConn.Close(); err != nil { -			errLog.Print(err) +	close(mc.closech) +	if mc.netConn == nil { +		return +	} +	if err := mc.netConn.Close(); err != nil { +		errLog.Print(err) +	} +} + +func (mc *mysqlConn) error() error { +	if mc.closed.IsSet() { +		if err := mc.canceled.Value(); err != nil { +			return err  		} -		mc.netConn = nil +		return ErrInvalidConn  	} -	mc.cfg = nil -	mc.buf.nc = nil +	return nil  }  func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) { -	if mc.netConn == nil { +	if mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	}  	// Send command  	err := mc.writeCommandPacketStr(comStmtPrepare, query)  	if err != nil { -		return nil, err +		return nil, mc.markBadConn(err)  	}  	stmt := &mysqlStmt{ @@ -145,7 +194,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin  	if buf == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return "", driver.ErrBadConn +		return "", ErrInvalidConn  	}  	buf = buf[:0]  	argPos := 0 @@ -258,7 +307,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin  }  func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, error) { -	if mc.netConn == nil { +	if mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	} @@ -272,7 +321,6 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err  			return nil, err  		}  		query = prepared -		args = nil  	}  	mc.affectedRows = 0  	mc.insertId = 0 @@ -284,14 +332,14 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err  			insertId:     int64(mc.insertId),  		}, err  	} -	return nil, err +	return nil, mc.markBadConn(err)  }  // Internal function to execute commands  func (mc *mysqlConn) exec(query string) error {  	// Send command  	if err := mc.writeCommandPacketStr(comQuery, query); err != nil { -		return err +		return mc.markBadConn(err)  	}  	// Read Result @@ -316,7 +364,11 @@ func (mc *mysqlConn) exec(query string) error {  }  func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) { -	if mc.netConn == nil { +	return mc.query(query, args) +} + +func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error) { +	if mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	} @@ -330,7 +382,6 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro  			return nil, err  		}  		query = prepared -		args = nil  	}  	// Send command  	err := mc.writeCommandPacketStr(comQuery, query) @@ -352,12 +403,13 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro  					return nil, err  				}  			} +  			// Columns  			rows.rs.columns, err = mc.readColumns(resLen)  			return rows, err  		}  	} -	return nil, err +	return nil, mc.markBadConn(err)  }  // Gets the value of the given MySQL System Variable @@ -389,3 +441,21 @@ func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {  	}  	return nil, err  } + +// finish is called when the query has canceled. +func (mc *mysqlConn) cancel(err error) { +	mc.canceled.Set(err) +	mc.cleanup() +} + +// finish is called when the query has succeeded. +func (mc *mysqlConn) finish() { +	if !mc.watching || mc.finished == nil { +		return +	} +	select { +	case mc.finished <- struct{}{}: +		mc.watching = false +	case <-mc.closech: +	} +} diff --git a/vendor/github.com/go-sql-driver/mysql/connection_go18.go b/vendor/github.com/go-sql-driver/mysql/connection_go18.go new file mode 100644 index 0000000..48a9cca --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/connection_go18.go @@ -0,0 +1,197 @@ +// 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) error { +	if mc.closed.IsSet() { +		errLog.Print(ErrInvalidConn) +		return driver.ErrBadConn +	} + +	if err := mc.watchCancel(ctx); err != nil { +		return err +	} +	defer mc.finish() + +	if err := mc.writeCommandPacket(comPing); err != nil { +		return err +	} +	if _, err := mc.readResultOK(); err != nil { +		return err +	} + +	return nil +} + +// 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 +			} +		} +	}() +} diff --git a/vendor/github.com/go-sql-driver/mysql/const.go b/vendor/github.com/go-sql-driver/mysql/const.go index 88cfff3..4a19ca5 100644 --- a/vendor/github.com/go-sql-driver/mysql/const.go +++ b/vendor/github.com/go-sql-driver/mysql/const.go @@ -9,7 +9,8 @@  package mysql  const ( -	minProtocolVersion byte = 10 +	defaultMaxAllowedPacket = 4 << 20 // 4 MiB +	minProtocolVersion      = 10  	maxPacketSize           = 1<<24 - 1  	timeFormat              = "2006-01-02 15:04:05.999999"  ) @@ -87,8 +88,10 @@ const (  )  // https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnType +type fieldType byte +  const ( -	fieldTypeDecimal byte = iota +	fieldTypeDecimal fieldType = iota  	fieldTypeTiny  	fieldTypeShort  	fieldTypeLong @@ -107,7 +110,7 @@ const (  	fieldTypeBit  )  const ( -	fieldTypeJSON byte = iota + 0xf5 +	fieldTypeJSON fieldType = iota + 0xf5  	fieldTypeNewDecimal  	fieldTypeEnum  	fieldTypeSet diff --git a/vendor/github.com/go-sql-driver/mysql/driver.go b/vendor/github.com/go-sql-driver/mysql/driver.go index 0022d1f..d42ce7a 100644 --- a/vendor/github.com/go-sql-driver/mysql/driver.go +++ b/vendor/github.com/go-sql-driver/mysql/driver.go @@ -4,7 +4,7 @@  // 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/. -// Package mysql provides a MySQL driver for Go's database/sql package +// Package mysql provides a MySQL driver for Go's database/sql package.  //  // The driver should be used via the database/sql package:  // @@ -22,6 +22,11 @@ import (  	"net"  ) +// watcher interface is used for context support (From Go 1.8) +type watcher interface { +	startWatcher() +} +  // MySQLDriver is exported to make the driver directly accessible.  // In general the driver is used via the database/sql package.  type MySQLDriver struct{} @@ -52,13 +57,13 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {  	mc := &mysqlConn{  		maxAllowedPacket: maxPacketSize,  		maxWriteSize:     maxPacketSize - 1, +		closech:          make(chan struct{}),  	}  	mc.cfg, err = ParseDSN(dsn)  	if err != nil {  		return nil, err  	}  	mc.parseTime = mc.cfg.ParseTime -	mc.strict = mc.cfg.Strict  	// Connect to Server  	if dial, ok := dials[mc.cfg.Net]; ok { @@ -81,6 +86,11 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {  		}  	} +	// Call startWatcher for context support (From Go 1.8) +	if s, ok := interface{}(mc).(watcher); ok { +		s.startWatcher() +	} +  	mc.buf = newBuffer(mc.netConn)  	// Set I/O timeouts diff --git a/vendor/github.com/go-sql-driver/mysql/dsn.go b/vendor/github.com/go-sql-driver/mysql/dsn.go index ac00dce..3ade963 100644 --- a/vendor/github.com/go-sql-driver/mysql/dsn.go +++ b/vendor/github.com/go-sql-driver/mysql/dsn.go @@ -15,6 +15,7 @@ import (  	"fmt"  	"net"  	"net/url" +	"sort"  	"strconv"  	"strings"  	"time" @@ -27,7 +28,9 @@ var (  	errInvalidDSNUnsafeCollation = errors.New("invalid DSN: interpolateParams can not be used with unsafe collations")  ) -// Config is a configuration parsed from a DSN string +// Config is a configuration parsed from a DSN string. +// If a new Config is created instead of being parsed from a DSN string, +// the NewConfig function should be used, which sets default values.  type Config struct {  	User             string            // Username  	Passwd           string            // Password (requires User) @@ -53,7 +56,45 @@ type Config struct {  	InterpolateParams       bool // Interpolate placeholders into query string  	MultiStatements         bool // Allow multiple statements in one query  	ParseTime               bool // Parse time values to time.Time -	Strict                  bool // Return warnings as errors +	RejectReadOnly          bool // Reject read-only connections +} + +// NewConfig creates a new Config and sets default values. +func NewConfig() *Config { +	return &Config{ +		Collation:            defaultCollation, +		Loc:                  time.UTC, +		MaxAllowedPacket:     defaultMaxAllowedPacket, +		AllowNativePasswords: true, +	} +} + +func (cfg *Config) normalize() error { +	if cfg.InterpolateParams && unsafeCollations[cfg.Collation] { +		return errInvalidDSNUnsafeCollation +	} + +	// Set default network if empty +	if cfg.Net == "" { +		cfg.Net = "tcp" +	} + +	// Set default address if empty +	if cfg.Addr == "" { +		switch cfg.Net { +		case "tcp": +			cfg.Addr = "127.0.0.1:3306" +		case "unix": +			cfg.Addr = "/tmp/mysql.sock" +		default: +			return errors.New("default addr for network '" + cfg.Net + "' unknown") +		} + +	} else if cfg.Net == "tcp" { +		cfg.Addr = ensureHavePort(cfg.Addr) +	} + +	return nil  }  // FormatDSN formats the given Config into a DSN string which can be passed to @@ -102,12 +143,12 @@ func (cfg *Config) FormatDSN() string {  		}  	} -	if cfg.AllowNativePasswords { +	if !cfg.AllowNativePasswords {  		if hasParam { -			buf.WriteString("&allowNativePasswords=true") +			buf.WriteString("&allowNativePasswords=false")  		} else {  			hasParam = true -			buf.WriteString("?allowNativePasswords=true") +			buf.WriteString("?allowNativePasswords=false")  		}  	} @@ -195,12 +236,12 @@ func (cfg *Config) FormatDSN() string {  		buf.WriteString(cfg.ReadTimeout.String())  	} -	if cfg.Strict { +	if cfg.RejectReadOnly {  		if hasParam { -			buf.WriteString("&strict=true") +			buf.WriteString("&rejectReadOnly=true")  		} else {  			hasParam = true -			buf.WriteString("?strict=true") +			buf.WriteString("?rejectReadOnly=true")  		}  	} @@ -234,7 +275,7 @@ func (cfg *Config) FormatDSN() string {  		buf.WriteString(cfg.WriteTimeout.String())  	} -	if cfg.MaxAllowedPacket > 0 { +	if cfg.MaxAllowedPacket != defaultMaxAllowedPacket {  		if hasParam {  			buf.WriteString("&maxAllowedPacket=")  		} else { @@ -247,7 +288,12 @@ func (cfg *Config) FormatDSN() string {  	// other params  	if cfg.Params != nil { -		for param, value := range cfg.Params { +		var params []string +		for param := range cfg.Params { +			params = append(params, param) +		} +		sort.Strings(params) +		for _, param := range params {  			if hasParam {  				buf.WriteByte('&')  			} else { @@ -257,7 +303,7 @@ func (cfg *Config) FormatDSN() string {  			buf.WriteString(param)  			buf.WriteByte('=') -			buf.WriteString(url.QueryEscape(value)) +			buf.WriteString(url.QueryEscape(cfg.Params[param]))  		}  	} @@ -267,10 +313,7 @@ func (cfg *Config) FormatDSN() string {  // ParseDSN parses the DSN string to a Config  func ParseDSN(dsn string) (cfg *Config, err error) {  	// New config with some default values -	cfg = &Config{ -		Loc:       time.UTC, -		Collation: defaultCollation, -	} +	cfg = NewConfig()  	// [user[:password]@][net[(addr)]]/dbname[?param1=value1¶mN=valueN]  	// Find the last '/' (since the password or the net addr might contain a '/') @@ -338,28 +381,9 @@ func ParseDSN(dsn string) (cfg *Config, err error) {  		return nil, errInvalidDSNNoSlash  	} -	if cfg.InterpolateParams && unsafeCollations[cfg.Collation] { -		return nil, errInvalidDSNUnsafeCollation +	if err = cfg.normalize(); err != nil { +		return nil, err  	} - -	// Set default network if empty -	if cfg.Net == "" { -		cfg.Net = "tcp" -	} - -	// Set default address if empty -	if cfg.Addr == "" { -		switch cfg.Net { -		case "tcp": -			cfg.Addr = "127.0.0.1:3306" -		case "unix": -			cfg.Addr = "/tmp/mysql.sock" -		default: -			return nil, errors.New("default addr for network '" + cfg.Net + "' unknown") -		} - -	} -  	return  } @@ -472,14 +496,18 @@ func parseDSNParams(cfg *Config, params string) (err error) {  				return  			} -		// Strict mode -		case "strict": +		// Reject read-only connections +		case "rejectReadOnly":  			var isBool bool -			cfg.Strict, isBool = readBool(value) +			cfg.RejectReadOnly, isBool = readBool(value)  			if !isBool {  				return errors.New("invalid bool value: " + value)  			} +		// Strict mode +		case "strict": +			panic("strict mode has been removed. See https://github.com/go-sql-driver/mysql/wiki/strict-mode") +  		// Dial Timeout  		case "timeout":  			cfg.Timeout, err = time.ParseDuration(value) @@ -494,6 +522,10 @@ func parseDSNParams(cfg *Config, params string) (err error) {  				if boolValue {  					cfg.TLSConfig = "true"  					cfg.tls = &tls.Config{} +					host, _, err := net.SplitHostPort(cfg.Addr) +					if err == nil { +						cfg.tls.ServerName = host +					}  				} else {  					cfg.TLSConfig = "false"  				} @@ -506,7 +538,7 @@ func parseDSNParams(cfg *Config, params string) (err error) {  					return fmt.Errorf("invalid value for TLS config name: %v", err)  				} -				if tlsConfig, ok := tlsConfigRegister[name]; ok { +				if tlsConfig := getTLSConfigClone(name); tlsConfig != nil {  					if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {  						host, _, err := net.SplitHostPort(cfg.Addr)  						if err == nil { @@ -546,3 +578,10 @@ func parseDSNParams(cfg *Config, params string) (err error) {  	return  } + +func ensureHavePort(addr string) string { +	if _, _, err := net.SplitHostPort(addr); err != nil { +		return net.JoinHostPort(addr, "3306") +	} +	return addr +} diff --git a/vendor/github.com/go-sql-driver/mysql/errors.go b/vendor/github.com/go-sql-driver/mysql/errors.go index 857854e..760782f 100644 --- a/vendor/github.com/go-sql-driver/mysql/errors.go +++ b/vendor/github.com/go-sql-driver/mysql/errors.go @@ -9,10 +9,8 @@  package mysql  import ( -	"database/sql/driver"  	"errors"  	"fmt" -	"io"  	"log"  	"os"  ) @@ -31,6 +29,12 @@ var (  	ErrPktSyncMul        = errors.New("commands out of sync. Did you run multiple statements at once?")  	ErrPktTooLarge       = errors.New("packet for query is too large. Try adjusting the 'max_allowed_packet' variable on the server")  	ErrBusyBuffer        = errors.New("busy buffer") + +	// errBadConnNoWrite is used for connection errors where nothing was sent to the database yet. +	// If this happens first in a function starting a database interaction, it should be replaced by driver.ErrBadConn +	// to trigger a resend. +	// See https://github.com/go-sql-driver/mysql/pull/302 +	errBadConnNoWrite = errors.New("bad connection")  )  var errLog = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile)) @@ -59,74 +63,3 @@ type MySQLError struct {  func (me *MySQLError) Error() string {  	return fmt.Sprintf("Error %d: %s", me.Number, me.Message)  } - -// MySQLWarnings is an error type which represents a group of one or more MySQL -// warnings -type MySQLWarnings []MySQLWarning - -func (mws MySQLWarnings) Error() string { -	var msg string -	for i, warning := range mws { -		if i > 0 { -			msg += "\r\n" -		} -		msg += fmt.Sprintf( -			"%s %s: %s", -			warning.Level, -			warning.Code, -			warning.Message, -		) -	} -	return msg -} - -// MySQLWarning is an error type which represents a single MySQL warning. -// Warnings are returned in groups only. See MySQLWarnings -type MySQLWarning struct { -	Level   string -	Code    string -	Message string -} - -func (mc *mysqlConn) getWarnings() (err error) { -	rows, err := mc.Query("SHOW WARNINGS", nil) -	if err != nil { -		return -	} - -	var warnings = MySQLWarnings{} -	var values = make([]driver.Value, 3) - -	for { -		err = rows.Next(values) -		switch err { -		case nil: -			warning := MySQLWarning{} - -			if raw, ok := values[0].([]byte); ok { -				warning.Level = string(raw) -			} else { -				warning.Level = fmt.Sprintf("%s", values[0]) -			} -			if raw, ok := values[1].([]byte); ok { -				warning.Code = string(raw) -			} else { -				warning.Code = fmt.Sprintf("%s", values[1]) -			} -			if raw, ok := values[2].([]byte); ok { -				warning.Message = string(raw) -			} else { -				warning.Message = fmt.Sprintf("%s", values[0]) -			} - -			warnings = append(warnings, warning) - -		case io.EOF: -			return warnings - -		default: -			rows.Close() -			return -		} -	} -} diff --git a/vendor/github.com/go-sql-driver/mysql/fields.go b/vendor/github.com/go-sql-driver/mysql/fields.go new file mode 100644 index 0000000..cded986 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/fields.go @@ -0,0 +1,140 @@ +// 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/. + +package mysql + +import ( +	"database/sql" +	"reflect" +) + +var typeDatabaseName = map[fieldType]string{ +	fieldTypeBit:        "BIT", +	fieldTypeBLOB:       "BLOB", +	fieldTypeDate:       "DATE", +	fieldTypeDateTime:   "DATETIME", +	fieldTypeDecimal:    "DECIMAL", +	fieldTypeDouble:     "DOUBLE", +	fieldTypeEnum:       "ENUM", +	fieldTypeFloat:      "FLOAT", +	fieldTypeGeometry:   "GEOMETRY", +	fieldTypeInt24:      "MEDIUMINT", +	fieldTypeJSON:       "JSON", +	fieldTypeLong:       "INT", +	fieldTypeLongBLOB:   "LONGBLOB", +	fieldTypeLongLong:   "BIGINT", +	fieldTypeMediumBLOB: "MEDIUMBLOB", +	fieldTypeNewDate:    "DATE", +	fieldTypeNewDecimal: "DECIMAL", +	fieldTypeNULL:       "NULL", +	fieldTypeSet:        "SET", +	fieldTypeShort:      "SMALLINT", +	fieldTypeString:     "CHAR", +	fieldTypeTime:       "TIME", +	fieldTypeTimestamp:  "TIMESTAMP", +	fieldTypeTiny:       "TINYINT", +	fieldTypeTinyBLOB:   "TINYBLOB", +	fieldTypeVarChar:    "VARCHAR", +	fieldTypeVarString:  "VARCHAR", +	fieldTypeYear:       "YEAR", +} + +var ( +	scanTypeFloat32   = reflect.TypeOf(float32(0)) +	scanTypeFloat64   = reflect.TypeOf(float64(0)) +	scanTypeInt8      = reflect.TypeOf(int8(0)) +	scanTypeInt16     = reflect.TypeOf(int16(0)) +	scanTypeInt32     = reflect.TypeOf(int32(0)) +	scanTypeInt64     = reflect.TypeOf(int64(0)) +	scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) +	scanTypeNullInt   = reflect.TypeOf(sql.NullInt64{}) +	scanTypeNullTime  = reflect.TypeOf(NullTime{}) +	scanTypeUint8     = reflect.TypeOf(uint8(0)) +	scanTypeUint16    = reflect.TypeOf(uint16(0)) +	scanTypeUint32    = reflect.TypeOf(uint32(0)) +	scanTypeUint64    = reflect.TypeOf(uint64(0)) +	scanTypeRawBytes  = reflect.TypeOf(sql.RawBytes{}) +	scanTypeUnknown   = reflect.TypeOf(new(interface{})) +) + +type mysqlField struct { +	tableName string +	name      string +	length    uint32 +	flags     fieldFlag +	fieldType fieldType +	decimals  byte +} + +func (mf *mysqlField) scanType() reflect.Type { +	switch mf.fieldType { +	case fieldTypeTiny: +		if mf.flags&flagNotNULL != 0 { +			if mf.flags&flagUnsigned != 0 { +				return scanTypeUint8 +			} +			return scanTypeInt8 +		} +		return scanTypeNullInt + +	case fieldTypeShort, fieldTypeYear: +		if mf.flags&flagNotNULL != 0 { +			if mf.flags&flagUnsigned != 0 { +				return scanTypeUint16 +			} +			return scanTypeInt16 +		} +		return scanTypeNullInt + +	case fieldTypeInt24, fieldTypeLong: +		if mf.flags&flagNotNULL != 0 { +			if mf.flags&flagUnsigned != 0 { +				return scanTypeUint32 +			} +			return scanTypeInt32 +		} +		return scanTypeNullInt + +	case fieldTypeLongLong: +		if mf.flags&flagNotNULL != 0 { +			if mf.flags&flagUnsigned != 0 { +				return scanTypeUint64 +			} +			return scanTypeInt64 +		} +		return scanTypeNullInt + +	case fieldTypeFloat: +		if mf.flags&flagNotNULL != 0 { +			return scanTypeFloat32 +		} +		return scanTypeNullFloat + +	case fieldTypeDouble: +		if mf.flags&flagNotNULL != 0 { +			return scanTypeFloat64 +		} +		return scanTypeNullFloat + +	case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar, +		fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB, +		fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB, +		fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON, +		fieldTypeTime: +		return scanTypeRawBytes + +	case fieldTypeDate, fieldTypeNewDate, +		fieldTypeTimestamp, fieldTypeDateTime: +		// NullTime is always returned for more consistent behavior as it can +		// handle both cases of parseTime regardless if the field is nullable. +		return scanTypeNullTime + +	default: +		return scanTypeUnknown +	} +} diff --git a/vendor/github.com/go-sql-driver/mysql/infile.go b/vendor/github.com/go-sql-driver/mysql/infile.go index 547357c..4020f91 100644 --- a/vendor/github.com/go-sql-driver/mysql/infile.go +++ b/vendor/github.com/go-sql-driver/mysql/infile.go @@ -147,7 +147,8 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {  	}  	// send content packets -	if err == nil { +	// if packetSize == 0, the Reader contains no data +	if err == nil && packetSize > 0 {  		data := make([]byte, 4+packetSize)  		var n int  		for err == nil { diff --git a/vendor/github.com/go-sql-driver/mysql/packets.go b/vendor/github.com/go-sql-driver/mysql/packets.go index 41b4d3d..f63d250 100644 --- a/vendor/github.com/go-sql-driver/mysql/packets.go +++ b/vendor/github.com/go-sql-driver/mysql/packets.go @@ -30,9 +30,12 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {  		// read packet header  		data, err := mc.buf.readNext(4)  		if err != nil { +			if cerr := mc.canceled.Value(); cerr != nil { +				return nil, cerr +			}  			errLog.Print(err)  			mc.Close() -			return nil, driver.ErrBadConn +			return nil, ErrInvalidConn  		}  		// packet length [24 bit] @@ -54,7 +57,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {  			if prevData == nil {  				errLog.Print(ErrMalformPkt)  				mc.Close() -				return nil, driver.ErrBadConn +				return nil, ErrInvalidConn  			}  			return prevData, nil @@ -63,9 +66,12 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {  		// read packet body [pktLen bytes]  		data, err = mc.buf.readNext(pktLen)  		if err != nil { +			if cerr := mc.canceled.Value(); cerr != nil { +				return nil, cerr +			}  			errLog.Print(err)  			mc.Close() -			return nil, driver.ErrBadConn +			return nil, ErrInvalidConn  		}  		// return data if this was the last packet @@ -125,11 +131,20 @@ func (mc *mysqlConn) writePacket(data []byte) error {  		// Handle error  		if err == nil { // n != len(data) +			mc.cleanup()  			errLog.Print(ErrMalformPkt)  		} else { +			if cerr := mc.canceled.Value(); cerr != nil { +				return cerr +			} +			if n == 0 && pktLen == len(data)-4 { +				// only for the first loop iteration when nothing was written yet +				return errBadConnNoWrite +			} +			mc.cleanup()  			errLog.Print(err)  		} -		return driver.ErrBadConn +		return ErrInvalidConn  	}  } @@ -263,7 +278,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// ClientFlags [32 bit] @@ -341,7 +356,9 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {  // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse  func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error {  	// User password -	scrambleBuff := scrambleOldPassword(cipher, []byte(mc.cfg.Passwd)) +	// https://dev.mysql.com/doc/internals/en/old-password-authentication.html +	// Old password authentication only need and will need 8-byte challenge. +	scrambleBuff := scrambleOldPassword(cipher[:8], []byte(mc.cfg.Passwd))  	// Calculate the packet length and add a tailing 0  	pktLen := len(scrambleBuff) + 1 @@ -349,7 +366,7 @@ func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add the scrambled password [null terminated string] @@ -368,7 +385,7 @@ func (mc *mysqlConn) writeClearAuthPacket() error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add the clear password [null terminated string] @@ -381,7 +398,9 @@ func (mc *mysqlConn) writeClearAuthPacket() error {  //  Native password authentication method  // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse  func (mc *mysqlConn) writeNativeAuthPacket(cipher []byte) error { -	scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.Passwd)) +	// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html +	// Native password authentication only need and will need 20-byte challenge. +	scrambleBuff := scramblePassword(cipher[0:20], []byte(mc.cfg.Passwd))  	// Calculate the packet length and add a tailing 0  	pktLen := len(scrambleBuff) @@ -389,7 +408,7 @@ func (mc *mysqlConn) writeNativeAuthPacket(cipher []byte) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add the scramble @@ -410,7 +429,7 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add command byte @@ -429,7 +448,7 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add command byte @@ -450,7 +469,7 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// Add command byte @@ -484,25 +503,26 @@ func (mc *mysqlConn) readResultOK() ([]byte, error) {  			if len(data) > 1 {  				pluginEndIndex := bytes.IndexByte(data, 0x00)  				plugin := string(data[1:pluginEndIndex]) -				cipher := data[pluginEndIndex+1 : len(data)-1] +				cipher := data[pluginEndIndex+1:] -				if plugin == "mysql_old_password" { +				switch plugin { +				case "mysql_old_password":  					// using old_passwords  					return cipher, ErrOldPassword -				} else if plugin == "mysql_clear_password" { +				case "mysql_clear_password":  					// using clear text password  					return cipher, ErrCleartextPassword -				} else if plugin == "mysql_native_password" { +				case "mysql_native_password":  					// using mysql default authentication method  					return cipher, ErrNativePassword -				} else { +				default:  					return cipher, ErrUnknownPlugin  				} -			} else { -				// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest -				return nil, ErrOldPassword  			} +			// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest +			return nil, ErrOldPassword +  		default: // Error otherwise  			return nil, mc.handleErrorPacket(data)  		} @@ -550,6 +570,22 @@ func (mc *mysqlConn) handleErrorPacket(data []byte) error {  	// Error Number [16 bit uint]  	errno := binary.LittleEndian.Uint16(data[1:3]) +	// 1792: ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION +	// 1290: ER_OPTION_PREVENTS_STATEMENT (returned by Aurora during failover) +	if (errno == 1792 || errno == 1290) && mc.cfg.RejectReadOnly { +		// Oops; we are connected to a read-only connection, and won't be able +		// to issue any write statements. Since RejectReadOnly is configured, +		// we throw away this connection hoping this one would have write +		// permission. This is specifically for a possible race condition +		// during failover (e.g. on AWS Aurora). See README.md for more. +		// +		// We explicitly close the connection before returning +		// driver.ErrBadConn to ensure that `database/sql` purges this +		// connection and initiates a new one for next statement next time. +		mc.Close() +		return driver.ErrBadConn +	} +  	pos := 3  	// SQL State [optional: # + 5bytes string] @@ -589,14 +625,7 @@ func (mc *mysqlConn) handleOkPacket(data []byte) error {  	}  	// warning count [2 bytes] -	if !mc.strict { -		return nil -	} -	pos := 1 + n + m + 2 -	if binary.LittleEndian.Uint16(data[pos:pos+2]) > 0 { -		return mc.getWarnings() -	}  	return nil  } @@ -671,11 +700,14 @@ func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {  		// Filler [uint8]  		// Charset [charset, collation uint8] +		pos += n + 1 + 2 +  		// Length [uint32] -		pos += n + 1 + 2 + 4 +		columns[i].length = binary.LittleEndian.Uint32(data[pos : pos+4]) +		pos += 4  		// Field type [uint8] -		columns[i].fieldType = data[pos] +		columns[i].fieldType = fieldType(data[pos])  		pos++  		// Flags [uint16] @@ -808,14 +840,7 @@ func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {  		// Reserved [8 bit]  		// Warning count [16 bit uint] -		if !stmt.mc.strict { -			return columnCount, nil -		} -		// Check for warnings count > 0, only available in MySQL > 4.1 -		if len(data) >= 12 && binary.LittleEndian.Uint16(data[10:12]) > 0 { -			return columnCount, stmt.mc.getWarnings() -		}  		return columnCount, nil  	}  	return 0, err @@ -900,7 +925,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  	if data == nil {  		// can not take the buffer. Something must be wrong with the connection  		errLog.Print(ErrBusyBuffer) -		return driver.ErrBadConn +		return errBadConnNoWrite  	}  	// command [1 byte] @@ -959,7 +984,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  			// build NULL-bitmap  			if arg == nil {  				nullMask[i/8] |= 1 << (uint(i) & 7) -				paramTypes[i+i] = fieldTypeNULL +				paramTypes[i+i] = byte(fieldTypeNULL)  				paramTypes[i+i+1] = 0x00  				continue  			} @@ -967,7 +992,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  			// cache types and values  			switch v := arg.(type) {  			case int64: -				paramTypes[i+i] = fieldTypeLongLong +				paramTypes[i+i] = byte(fieldTypeLongLong)  				paramTypes[i+i+1] = 0x00  				if cap(paramValues)-len(paramValues)-8 >= 0 { @@ -983,7 +1008,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  				}  			case float64: -				paramTypes[i+i] = fieldTypeDouble +				paramTypes[i+i] = byte(fieldTypeDouble)  				paramTypes[i+i+1] = 0x00  				if cap(paramValues)-len(paramValues)-8 >= 0 { @@ -999,7 +1024,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  				}  			case bool: -				paramTypes[i+i] = fieldTypeTiny +				paramTypes[i+i] = byte(fieldTypeTiny)  				paramTypes[i+i+1] = 0x00  				if v { @@ -1011,7 +1036,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  			case []byte:  				// Common case (non-nil value) first  				if v != nil { -					paramTypes[i+i] = fieldTypeString +					paramTypes[i+i] = byte(fieldTypeString)  					paramTypes[i+i+1] = 0x00  					if len(v) < mc.maxAllowedPacket-pos-len(paramValues)-(len(args)-(i+1))*64 { @@ -1029,11 +1054,11 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  				// Handle []byte(nil) as a NULL value  				nullMask[i/8] |= 1 << (uint(i) & 7) -				paramTypes[i+i] = fieldTypeNULL +				paramTypes[i+i] = byte(fieldTypeNULL)  				paramTypes[i+i+1] = 0x00  			case string: -				paramTypes[i+i] = fieldTypeString +				paramTypes[i+i] = byte(fieldTypeString)  				paramTypes[i+i+1] = 0x00  				if len(v) < mc.maxAllowedPacket-pos-len(paramValues)-(len(args)-(i+1))*64 { @@ -1048,20 +1073,22 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {  				}  			case time.Time: -				paramTypes[i+i] = fieldTypeString +				paramTypes[i+i] = byte(fieldTypeString)  				paramTypes[i+i+1] = 0x00 -				var val []byte +				var a [64]byte +				var b = a[:0] +  				if v.IsZero() { -					val = []byte("0000-00-00") +					b = append(b, "0000-00-00"...)  				} else { -					val = []byte(v.In(mc.cfg.Loc).Format(timeFormat)) +					b = v.In(mc.cfg.Loc).AppendFormat(b, timeFormat)  				}  				paramValues = appendLengthEncodedInteger(paramValues, -					uint64(len(val)), +					uint64(len(b)),  				) -				paramValues = append(paramValues, val...) +				paramValues = append(paramValues, b...)  			default:  				return fmt.Errorf("can not convert type: %T", arg) @@ -1120,10 +1147,11 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {  			}  			return io.EOF  		} +		mc := rows.mc  		rows.mc = nil  		// Error otherwise -		return rows.mc.handleErrorPacket(data) +		return mc.handleErrorPacket(data)  	}  	// NULL-bitmap,  [(column-count + 7 + 2) / 8 bytes] @@ -1187,7 +1215,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {  			continue  		case fieldTypeFloat: -			dest[i] = float32(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))) +			dest[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))  			pos += 4  			continue diff --git a/vendor/github.com/go-sql-driver/mysql/rows.go b/vendor/github.com/go-sql-driver/mysql/rows.go index 900f548..18f4169 100644 --- a/vendor/github.com/go-sql-driver/mysql/rows.go +++ b/vendor/github.com/go-sql-driver/mysql/rows.go @@ -11,34 +11,24 @@ package mysql  import (  	"database/sql/driver"  	"io" +	"math" +	"reflect"  ) -type mysqlField struct { -	tableName string -	name      string -	flags     fieldFlag -	fieldType byte -	decimals  byte -} -  type resultSet struct { -	columns []mysqlField -	done    bool +	columns     []mysqlField +	columnNames []string +	done        bool  }  type mysqlRows struct { -	mc *mysqlConn -	rs resultSet +	mc     *mysqlConn +	rs     resultSet +	finish func()  }  type binaryRows struct {  	mysqlRows -	// stmtCols is a pointer to the statement's cached columns for different -	// result sets. -	stmtCols *[][]mysqlField -	// i is a number of the current result set. It is used to fetch proper -	// columns from stmtCols. -	i int  }  type textRows struct { @@ -46,6 +36,10 @@ type textRows struct {  }  func (rows *mysqlRows) Columns() []string { +	if rows.rs.columnNames != nil { +		return rows.rs.columnNames +	} +  	columns := make([]string, len(rows.rs.columns))  	if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias {  		for i := range columns { @@ -60,16 +54,64 @@ func (rows *mysqlRows) Columns() []string {  			columns[i] = rows.rs.columns[i].name  		}  	} + +	rows.rs.columnNames = columns  	return columns  } +func (rows *mysqlRows) ColumnTypeDatabaseTypeName(i int) string { +	if name, ok := typeDatabaseName[rows.rs.columns[i].fieldType]; ok { +		return name +	} +	return "" +} + +// func (rows *mysqlRows) ColumnTypeLength(i int) (length int64, ok bool) { +// 	return int64(rows.rs.columns[i].length), true +// } + +func (rows *mysqlRows) ColumnTypeNullable(i int) (nullable, ok bool) { +	return rows.rs.columns[i].flags&flagNotNULL == 0, true +} + +func (rows *mysqlRows) ColumnTypePrecisionScale(i int) (int64, int64, bool) { +	column := rows.rs.columns[i] +	decimals := int64(column.decimals) + +	switch column.fieldType { +	case fieldTypeDecimal, fieldTypeNewDecimal: +		if decimals > 0 { +			return int64(column.length) - 2, decimals, true +		} +		return int64(column.length) - 1, decimals, true +	case fieldTypeTimestamp, fieldTypeDateTime, fieldTypeTime: +		return decimals, decimals, true +	case fieldTypeFloat, fieldTypeDouble: +		if decimals == 0x1f { +			return math.MaxInt64, math.MaxInt64, true +		} +		return math.MaxInt64, decimals, true +	} + +	return 0, 0, false +} + +func (rows *mysqlRows) ColumnTypeScanType(i int) reflect.Type { +	return rows.rs.columns[i].scanType() +} +  func (rows *mysqlRows) Close() (err error) { +	if f := rows.finish; f != nil { +		f() +		rows.finish = nil +	} +  	mc := rows.mc  	if mc == nil {  		return nil  	} -	if mc.netConn == nil { -		return ErrInvalidConn +	if err := mc.error(); err != nil { +		return err  	}  	// Remove unread packets from stream @@ -97,8 +139,8 @@ func (rows *mysqlRows) nextResultSet() (int, error) {  	if rows.mc == nil {  		return 0, io.EOF  	} -	if rows.mc.netConn == nil { -		return 0, ErrInvalidConn +	if err := rows.mc.error(); err != nil { +		return 0, err  	}  	// Remove unread packets from stream @@ -132,31 +174,20 @@ func (rows *mysqlRows) nextNotEmptyResultSet() (int, error) {  	}  } -func (rows *binaryRows) NextResultSet() (err error) { +func (rows *binaryRows) NextResultSet() error {  	resLen, err := rows.nextNotEmptyResultSet()  	if err != nil {  		return err  	} -	// get columns, if not cached, read them and cache them. -	if rows.i >= len(*rows.stmtCols) { -		rows.rs.columns, err = rows.mc.readColumns(resLen) -		*rows.stmtCols = append(*rows.stmtCols, rows.rs.columns) -	} else { -		rows.rs.columns = (*rows.stmtCols)[rows.i] -		if err := rows.mc.readUntilEOF(); err != nil { -			return err -		} -	} - -	rows.i++ -	return nil +	rows.rs.columns, err = rows.mc.readColumns(resLen) +	return err  }  func (rows *binaryRows) Next(dest []driver.Value) error {  	if mc := rows.mc; mc != nil { -		if mc.netConn == nil { -			return ErrInvalidConn +		if err := mc.error(); err != nil { +			return err  		}  		// Fetch next row from stream @@ -177,8 +208,8 @@ func (rows *textRows) NextResultSet() (err error) {  func (rows *textRows) Next(dest []driver.Value) error {  	if mc := rows.mc; mc != nil { -		if mc.netConn == nil { -			return ErrInvalidConn +		if err := mc.error(); err != nil { +			return err  		}  		// Fetch next row from stream diff --git a/vendor/github.com/go-sql-driver/mysql/statement.go b/vendor/github.com/go-sql-driver/mysql/statement.go index b887716..ae22350 100644 --- a/vendor/github.com/go-sql-driver/mysql/statement.go +++ b/vendor/github.com/go-sql-driver/mysql/statement.go @@ -20,11 +20,10 @@ type mysqlStmt struct {  	mc         *mysqlConn  	id         uint32  	paramCount int -	columns    [][]mysqlField // cached from the first query  }  func (stmt *mysqlStmt) Close() error { -	if stmt.mc == nil || stmt.mc.netConn == nil { +	if stmt.mc == nil || stmt.mc.closed.IsSet() {  		// driver.Stmt.Close can be called more than once, thus this function  		// has to be idempotent.  		// See also Issue #450 and golang/go#16019. @@ -46,14 +45,14 @@ func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {  }  func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { -	if stmt.mc.netConn == nil { +	if stmt.mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	}  	// Send command  	err := stmt.writeExecutePacket(args)  	if err != nil { -		return nil, err +		return nil, stmt.mc.markBadConn(err)  	}  	mc := stmt.mc @@ -90,14 +89,18 @@ func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {  }  func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { -	if stmt.mc.netConn == nil { +	return stmt.query(args) +} + +func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) { +	if stmt.mc.closed.IsSet() {  		errLog.Print(ErrInvalidConn)  		return nil, driver.ErrBadConn  	}  	// Send command  	err := stmt.writeExecutePacket(args)  	if err != nil { -		return nil, err +		return nil, stmt.mc.markBadConn(err)  	}  	mc := stmt.mc @@ -109,20 +112,10 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {  	}  	rows := new(binaryRows) -	rows.stmtCols = &stmt.columns  	if resLen > 0 {  		rows.mc = mc -		rows.i++ -		// Columns -		// If not cached, read them and cache them -		if len(stmt.columns) == 0 { -			rows.rs.columns, err = mc.readColumns(resLen) -			stmt.columns = append(stmt.columns, rows.rs.columns) -		} else { -			rows.rs.columns = stmt.columns[0] -			err = mc.readUntilEOF() -		} +		rows.rs.columns, err = mc.readColumns(resLen)  	} else {  		rows.rs.done = true diff --git a/vendor/github.com/go-sql-driver/mysql/transaction.go b/vendor/github.com/go-sql-driver/mysql/transaction.go index 33c749b..417d727 100644 --- a/vendor/github.com/go-sql-driver/mysql/transaction.go +++ b/vendor/github.com/go-sql-driver/mysql/transaction.go @@ -13,7 +13,7 @@ type mysqlTx struct {  }  func (tx *mysqlTx) Commit() (err error) { -	if tx.mc == nil || tx.mc.netConn == nil { +	if tx.mc == nil || tx.mc.closed.IsSet() {  		return ErrInvalidConn  	}  	err = tx.mc.exec("COMMIT") @@ -22,7 +22,7 @@ func (tx *mysqlTx) Commit() (err error) {  }  func (tx *mysqlTx) Rollback() (err error) { -	if tx.mc == nil || tx.mc.netConn == nil { +	if tx.mc == nil || tx.mc.closed.IsSet() {  		return ErrInvalidConn  	}  	err = tx.mc.exec("ROLLBACK") diff --git a/vendor/github.com/go-sql-driver/mysql/utils.go b/vendor/github.com/go-sql-driver/mysql/utils.go index d523b7f..82da830 100644 --- a/vendor/github.com/go-sql-driver/mysql/utils.go +++ b/vendor/github.com/go-sql-driver/mysql/utils.go @@ -16,16 +16,21 @@ import (  	"fmt"  	"io"  	"strings" +	"sync" +	"sync/atomic"  	"time"  )  var ( +	tlsConfigLock     sync.RWMutex  	tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs  )  // RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.  // Use the key as a value in the DSN where tls=value.  // +// Note: The tls.Config provided to needs to be exclusively owned by the driver after registering. +//  //  rootCertPool := x509.NewCertPool()  //  pem, err := ioutil.ReadFile("/path/ca-cert.pem")  //  if err != nil { @@ -51,19 +56,32 @@ func RegisterTLSConfig(key string, config *tls.Config) error {  		return fmt.Errorf("key '%s' is reserved", key)  	} +	tlsConfigLock.Lock()  	if tlsConfigRegister == nil {  		tlsConfigRegister = make(map[string]*tls.Config)  	}  	tlsConfigRegister[key] = config +	tlsConfigLock.Unlock()  	return nil  }  // DeregisterTLSConfig removes the tls.Config associated with key.  func DeregisterTLSConfig(key string) { +	tlsConfigLock.Lock()  	if tlsConfigRegister != nil {  		delete(tlsConfigRegister, key)  	} +	tlsConfigLock.Unlock() +} + +func getTLSConfigClone(key string) (config *tls.Config) { +	tlsConfigLock.RLock() +	if v, ok := tlsConfigRegister[key]; ok { +		config = cloneTLSConfig(v) +	} +	tlsConfigLock.RUnlock() +	return  }  // Returns the bool value of the input. @@ -738,3 +756,67 @@ func escapeStringQuotes(buf []byte, v string) []byte {  	return buf[:pos]  } + +/****************************************************************************** +*                               Sync utils                                    * +******************************************************************************/ + +// noCopy may be embedded into structs which must not be copied +// after the first use. +// +// See https://github.com/golang/go/issues/8005#issuecomment-190753527 +// for details. +type noCopy struct{} + +// Lock is a no-op used by -copylocks checker from `go vet`. +func (*noCopy) Lock() {} + +// atomicBool is a wrapper around uint32 for usage as a boolean value with +// atomic access. +type atomicBool struct { +	_noCopy noCopy +	value   uint32 +} + +// IsSet returns wether the current boolean value is true +func (ab *atomicBool) IsSet() bool { +	return atomic.LoadUint32(&ab.value) > 0 +} + +// Set sets the value of the bool regardless of the previous value +func (ab *atomicBool) Set(value bool) { +	if value { +		atomic.StoreUint32(&ab.value, 1) +	} else { +		atomic.StoreUint32(&ab.value, 0) +	} +} + +// TrySet sets the value of the bool and returns wether the value changed +func (ab *atomicBool) TrySet(value bool) bool { +	if value { +		return atomic.SwapUint32(&ab.value, 1) == 0 +	} +	return atomic.SwapUint32(&ab.value, 0) > 0 +} + +// atomicBool is a wrapper for atomically accessed error values +type atomicError struct { +	_noCopy noCopy +	value   atomic.Value +} + +// Set sets the error value regardless of the previous value. +// The value must not be nil +func (ae *atomicError) Set(value error) { +	ae.value.Store(value) +} + +// Value returns the current error value +func (ae *atomicError) Value() error { +	if v := ae.value.Load(); v != nil { +		// this will panic if the value doesn't implement the error interface +		return v.(error) +	} +	return nil +} diff --git a/vendor/github.com/go-sql-driver/mysql/utils_go17.go b/vendor/github.com/go-sql-driver/mysql/utils_go17.go new file mode 100644 index 0000000..f595634 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/utils_go17.go @@ -0,0 +1,40 @@ +// 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, +	} +} diff --git a/vendor/github.com/go-sql-driver/mysql/utils_go18.go b/vendor/github.com/go-sql-driver/mysql/utils_go18.go new file mode 100644 index 0000000..7d8c9b1 --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/utils_go18.go @@ -0,0 +1,49 @@ +// 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" +) + +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 "", errors.New("mysql: unsupported isolation level: " + string(level)) +	} +} diff --git a/vendor/github.com/go-sql-driver/mysql/utils_legacy.go b/vendor/github.com/go-sql-driver/mysql/utils_legacy.go new file mode 100644 index 0000000..a03b10d --- /dev/null +++ b/vendor/github.com/go-sql-driver/mysql/utils_legacy.go @@ -0,0 +1,18 @@ +// 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 + +package mysql + +import "crypto/tls" + +func cloneTLSConfig(c *tls.Config) *tls.Config { +	clone := *c +	return &clone +}  | 
