Browse Source

vendor: update github.com/go-sql-driver/mysql

Unknwon 6 years ago
parent
commit
93f3a7f96a
25 changed files with 2188 additions and 793 deletions
  1. 37 0
      vendor/github.com/go-sql-driver/mysql/AUTHORS
  2. 75 11
      vendor/github.com/go-sql-driver/mysql/CHANGELOG.md
  3. 0 21
      vendor/github.com/go-sql-driver/mysql/ISSUE_TEMPLATE.md
  4. 0 9
      vendor/github.com/go-sql-driver/mysql/PULL_REQUEST_TEMPLATE.md
  5. 118 48
      vendor/github.com/go-sql-driver/mysql/README.md
  6. 1 1
      vendor/github.com/go-sql-driver/mysql/appengine.go
  7. 420 0
      vendor/github.com/go-sql-driver/mysql/auth.go
  8. 6 6
      vendor/github.com/go-sql-driver/mysql/buffer.go
  9. 1 0
      vendor/github.com/go-sql-driver/mysql/collations.go
  10. 123 34
      vendor/github.com/go-sql-driver/mysql/connection.go
  11. 208 0
      vendor/github.com/go-sql-driver/mysql/connection_go18.go
  12. 18 7
      vendor/github.com/go-sql-driver/mysql/const.go
  13. 50 48
      vendor/github.com/go-sql-driver/mysql/driver.go
  14. 156 58
      vendor/github.com/go-sql-driver/mysql/dsn.go
  15. 8 74
      vendor/github.com/go-sql-driver/mysql/errors.go
  16. 194 0
      vendor/github.com/go-sql-driver/mysql/fields.go
  17. 2 1
      vendor/github.com/go-sql-driver/mysql/infile.go
  18. 234 179
      vendor/github.com/go-sql-driver/mysql/packets.go
  19. 139 35
      vendor/github.com/go-sql-driver/mysql/rows.go
  20. 93 32
      vendor/github.com/go-sql-driver/mysql/statement.go
  21. 2 2
      vendor/github.com/go-sql-driver/mysql/transaction.go
  22. 210 224
      vendor/github.com/go-sql-driver/mysql/utils.go
  23. 40 0
      vendor/github.com/go-sql-driver/mysql/utils_go17.go
  24. 50 0
      vendor/github.com/go-sql-driver/mysql/utils_go18.go
  25. 3 3
      vendor/vendor.json

+ 37 - 0
vendor/github.com/go-sql-driver/mysql/AUTHORS

@@ -12,41 +12,78 @@
 # Individual Persons
 
 Aaron Hopkins <go-sql-driver at die.net>
+Achille Roussel <achille.roussel at gmail.com>
+Alexey Palazhchenko <alexey.palazhchenko at gmail.com>
+Andrew Reid <andrew.reid at tixtrack.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>
+Craig Wilson <craiggwilson at gmail.com>
+Daniel Montoya <dsmontoyam at gmail.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>
+Hajime Nakagami <nakagami 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 Li <jli at j-li.net>
+Justin Nuß <nuss.justin at gmail.com>
 Kamil Dziedzic <kamil at klecza.pl>
 Kevin Malachowski <kevin at chowski.com>
+Kieron Woodhouse <kieron.woodhouse at infosum.com>
+Lennart Rudolph <lrudolph at hmc.edu>
 Leonardo YongUk Kim <dalinaum at gmail.com>
+Linh Tran Tuan <linhduonggnu 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 at 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>
+Reed Allman <rdallman10 at gmail.com>
+Richard Wilkes <wilkes at me.com>
+Robert Russell <robert at rrbrussell.com>
 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>
+Xiangyu Hu <xiangyu.hu at outlook.com>
 Xiaobing Jiang <s7v7nislands at gmail.com>
 Xiuming Chen <cc at cxm.cc>
+Zhenye Xie <xiezhenye at gmail.com>
 
 # Organizations
 
 Barracuda Networks, Inc.
+Counting Ltd.
 Google Inc.
+InfoSum Ltd.
+Keybase Inc.
+Percona LLC
+Pivotal Inc.
 Stripe Inc.

+ 75 - 11
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md

@@ -1,18 +1,83 @@
-## HEAD
+## Version 1.4 (2018-06-03)
+
+Changes:
+
+ - Documentation fixes (#530, #535, #567)
+ - Refactoring (#575, #579, #580, #581, #603, #615, #704)
+ - Cache column names (#444)
+ - Sort the DSN parameters in DSNs generated from a config (#637)
+ - Allow native password authentication by default (#644)
+ - Use the default port if it is missing in the DSN (#668)
+ - Removed the `strict` mode (#676)
+ - Do not query `max_allowed_packet` by default (#680)
+ - Dropped support Go 1.6 and lower (#696)
+ - Updated `ConvertValue()` to match the database/sql/driver implementation (#760)
+ - Document the usage of `0000-00-00T00:00:00` as the time.Time zero value (#783)
+ - Improved the compatibility of the authentication system (#807)
+
+New Features:
+
+ - Multi-Results support (#537)
+ - `rejectReadOnly` DSN option (#604)
+ - `context.Context` support (#608, #612, #627, #761)
+ - Transaction isolation level support (#619, #744)
+ - Read-Only transactions support (#618, #634)
+ - `NewConfig` function which initializes a config with default values (#679)
+ - Implemented the `ColumnType` interfaces (#667, #724)
+ - Support for custom string types in `ConvertValue` (#623)
+ - Implemented `NamedValueChecker`, improving support for uint64 with high bit set (#690, #709, #710)
+ - `caching_sha2_password` authentication plugin support (#794, #800, #801, #802)
+ - Implemented `driver.SessionResetter` (#779)
+ - `sha256_password` authentication plugin support (#808)
+
+Bugfixes:
+
+ - Use the DSN hostname as TLS default ServerName if `tls=true` (#564, #718)
+ - Fixed LOAD LOCAL DATA INFILE for empty files (#590)
+ - Removed columns definition cache since it sometimes cached invalid data (#592)
+ - Don't mutate registered TLS configs (#600)
+ - Make RegisterTLSConfig concurrency-safe (#613)
+ - Handle missing auth data in the handshake packet correctly (#646)
+ - Do not retry queries when data was written to avoid data corruption (#302, #736)
+ - Cache the connection pointer for error handling before invalidating it (#678)
+ - Fixed imports for appengine/cloudsql (#700)
+ - Fix sending STMT_LONG_DATA for 0 byte data (#734)
+ - Set correct capacity for []bytes read from length-encoded strings (#766)
+ - Make RegisterDial concurrency-safe (#773)
+
+
+## Version 1.3 (2016-12-01)
 
 Changes:
 
  - Go 1.1 is no longer supported
- - Use decimals field from MySQL to format time types (#249)
+ - Use decimals fields in MySQL to format time types (#249)
  - Buffer optimizations (#269)
  - TLS ServerName defaults to the host (#283)
+ - Refactoring (#400, #410, #437)
+ - Adjusted documentation for second generation CloudSQL (#485)
+ - Documented DSN system var quoting rules (#502)
+ - Made statement.Close() calls idempotent to avoid errors in Go 1.6+ (#512)
 
-Bugfixes:
+New Features:
 
  - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP (#249)
+ - Support for returning table alias on Columns() (#289, #359, #382)
+ - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318, #490)
+ - Support for uint64 parameters with high bit set (#332, #345)
+ - Cleartext authentication plugin support (#327)
+ - Exported ParseDSN function and the Config struct (#403, #419, #429)
+ - Read / Write timeouts (#401)
+ - Support for JSON field type (#414)
+ - Support for multi-statements and multi-results (#411, #431)
+ - DSN parameter to set the driver-side max_allowed_packet value manually (#489)
+ - Native password authentication plugin support (#494, #524)
+
+Bugfixes:
+
  - Fixed handling of queries without columns and rows (#255)
  - Fixed a panic when SetKeepAlive() failed (#298)
- - Support receiving ERR packet while reading rows (#321)
+ - Handle ERR packets while reading rows (#321)
  - Fixed reading NULL length-encoded integers in MySQL 5.6+ (#349)
  - Fixed absolute paths support in LOAD LOCAL DATA INFILE (#356)
  - Actually zero out bytes in handshake response (#378)
@@ -20,13 +85,12 @@ Bugfixes:
  - Fixed tests with MySQL 5.7.9+ (#380)
  - QueryUnescape TLS config names (#397)
  - Fixed "broken pipe" error by writing to closed socket (#390)
-
-New Features:
- - Support for returning table alias on Columns() (#289, #359, #382)
- - Placeholder interpolation, can be actived with the DSN parameter `interpolateParams=true` (#309, #318)
- - Support for uint64 parameters with high bit set (#332, #345)
- - Cleartext authentication plugin support (#327)
-
+ - Fixed LOAD LOCAL DATA INFILE buffering (#424)
+ - Fixed parsing of floats into float64 when placeholders are used (#434)
+ - Fixed DSN tests with Go 1.7+ (#459)
+ - Handle ERR packets while waiting for EOF (#473)
+ - Invalidate connection on error while discarding additional results (#513)
+ - Allow terminating packets of length 0 (#516)
 
 
 ## Version 1.2 (2014-06-03)

+ 0 - 21
vendor/github.com/go-sql-driver/mysql/ISSUE_TEMPLATE.md

@@ -1,21 +0,0 @@
-### Issue description
-Tell us what should happen and what happens instead
-
-### Example code
-```go
-If possible, please enter some example code here to reproduce the issue.
-```
-
-### Error log
-```
-If you have an error log, please paste it here.
-```
-
-### Configuration
-*Driver version (or git SHA):*
-
-*Go version:* run `go version` in your console
-
-*Server version:* E.g. MySQL 5.6, MariaDB 10.0.20
-
-*Server OS:* E.g. Debian 8.1 (Jessie), Windows 10

+ 0 - 9
vendor/github.com/go-sql-driver/mysql/PULL_REQUEST_TEMPLATE.md

@@ -1,9 +0,0 @@
-### Description
-Please explain the changes you made here.
-
-### Checklist
-- [ ] Code compiles correctly
-- [ ] Created tests which fail without the change (if possible)
-- [ ] All tests passing
-- [ ] Extended the README / documentation, if necessary
-- [ ] Added myself / the copyright holder to the AUTHORS file

+ 118 - 48
vendor/github.com/go-sql-driver/mysql/README.md

@@ -1,13 +1,9 @@
 # Go-MySQL-Driver
 
-A MySQL-Driver for Go's [database/sql](http://golang.org/pkg/database/sql) package
+A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) package
 
 ![Go-MySQL-Driver logo](https://raw.github.com/wiki/go-sql-driver/mysql/gomysql_m.png "Golang Gopher holding the MySQL Dolphin")
 
-**Latest stable Release:** [Version 1.2 (June 03, 2014)](https://github.com/go-sql-driver/mysql/releases)
-
-[![Build Status](https://travis-ci.org/go-sql-driver/mysql.png?branch=master)](https://travis-ci.org/go-sql-driver/mysql)
-
 ---------------------------------------
   * [Features](#features)
   * [Requirements](#requirements)
@@ -19,6 +15,9 @@ A MySQL-Driver for Go's [database/sql](http://golang.org/pkg/database/sql) packa
       * [Address](#address)
       * [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)
@@ -30,31 +29,31 @@ A MySQL-Driver for Go's [database/sql](http://golang.org/pkg/database/sql) packa
 ## Features
   * Lightweight and [fast](https://github.com/go-sql-driver/sql-benchmark "golang MySQL-Driver performance")
   * Native Go implementation. No C-bindings, just pure Go
-  * Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](http://godoc.org/github.com/go-sql-driver/mysql#DialFunc)
+  * Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](https://godoc.org/github.com/go-sql-driver/mysql#DialFunc)
   * Automatic handling of broken connections
   * Automatic Connection Pooling *(by database/sql package)*
   * Supports queries larger than 16MB
-  * Full [`sql.RawBytes`](http://golang.org/pkg/database/sql/#RawBytes) support.
+  * Full [`sql.RawBytes`](https://golang.org/pkg/database/sql/#RawBytes) support.
   * Intelligent `LONG DATA` handling in prepared statements
   * Secure `LOAD DATA LOCAL INFILE` support with file Whitelisting and `io.Reader` support
   * Optional `time.Time` parsing
   * Optional placeholder interpolation
 
 ## Requirements
-  * Go 1.2 or higher
+  * Go 1.7 or higher. We aim to support the 3 latest versions of Go.
   * MySQL (4.1+), MariaDB, Percona Server, Google CloudSQL or Sphinx (2.2.3+)
 
 ---------------------------------------
 
 ## Installation
-Simple install the package to your [$GOPATH](http://code.google.com/p/go-wiki/wiki/GOPATH "GOPATH") with the [go tool](http://golang.org/cmd/go/ "go command") from shell:
+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](http://git-scm.com/downloads) on your machine and in your system's `PATH`.
+Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`.
 
 ## Usage
-_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](http://golang.org/pkg/database/sql) API then.
+_Go MySQL Driver_ is an implementation of Go's `database/sql/driver` interface. You only need to import the driver and can use the full [`database/sql`](https://golang.org/pkg/database/sql/) API then.
 
 Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name)  as `dataSourceName`:
 ```go
@@ -99,13 +98,14 @@ Alternatively, [Config.FormatDSN](https://godoc.org/github.com/go-sql-driver/mys
 Passwords can consist of any character. Escaping is **not** necessary.
 
 #### Protocol
-See [net.Dial](http://golang.org/pkg/net/#Dial) for more information which networks are available.
+See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which networks are available.
 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](http://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](http://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form.
+The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form.
 
 For Unix domain sockets the address is the absolute path to the MySQL-Server-socket, e.g. `/var/run/mysqld/mysqld.sock` or `/tmp/mysql.sock`.
 
@@ -135,6 +135,15 @@ Default:        false
 
 `allowCleartextPasswords=true` allows using the [cleartext client side plugin](http://dev.mysql.com/doc/en/cleartext-authentication-plugin.html) if required by an account, such as one defined with the [PAM authentication plugin](http://dev.mysql.com/doc/en/pam-authentication-plugin.html). Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include [TLS / SSL](#tls), IPsec, or a private network.
 
+##### `allowNativePasswords`
+
+```
+Type:           bool
+Valid Values:   true, false
+Default:        true
+```
+`allowNativePasswords=false` disallows the usage of MySQL native password method.
+
 ##### `allowOldPasswords`
 
 ```
@@ -215,11 +224,19 @@ Valid Values:   <escaped name>
 Default:        UTC
 ```
 
-Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](http://golang.org/pkg/time/#LoadLocation) for details.
+Sets the location for time.Time values (when using `parseTime=true`). *"Local"* sets the system's location. See [time.LoadLocation](https://golang.org/pkg/time/#LoadLocation) for details.
 
 Note that this sets the location for time.Time values but does not change MySQL's [time_zone setting](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html). For that see the [time_zone system variable](#system-variables), which can also be set as a DSN parameter.
 
-Please keep in mind, that param values must be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`.
+Please keep in mind, that param values must be [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)'ed. Alternatively you can manually replace the `/` with `%2F`. For example `US/Pacific` would be `loc=US%2FPacific`.
+
+##### `maxAllowedPacket`
+```
+Type:          decimal number
+Default:       4194304
+```
+
+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`
 
@@ -233,7 +250,6 @@ Allow multiple statements in one query. While this allows batch queries, it also
 
 When `multiStatements` is used, `?` parameters must only be used in the first statement.
 
-
 ##### `parseTime`
 
 ```
@@ -243,19 +259,19 @@ Default:        false
 ```
 
 `parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string`
+The date or datetime like `0000-00-00 00:00:00` is converted into zero value of `time.Time`.
 
 
 ##### `readTimeout`
 
 ```
-Type:           decimal number
+Type:           duration
 Default:        0
 ```
 
-I/O read timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*.
+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
@@ -263,19 +279,49 @@ Valid Values:   true, false
 Default:        false
 ```
 
-`strict=true` enables the strict mode in which MySQL warnings are treated as errors.
 
-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. See the [examples](#examples) for an DSN example.
+`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.
+
+
+##### `serverPubKey`
+
+```
+Type:           string
+Valid Values:   <name>
+Default:        none
+```
+
+Server public keys can be registered with [`mysql.RegisterServerPubKey`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterServerPubKey), which can then be used by the assigned name in the DSN.
+Public keys are used to transmit encrypted data, e.g. for authentication.
+If the server's public key is known, it should be set manually to avoid expensive and potentially insecure transmissions of the public key from the server to the client each time it is required.
 
 
 ##### `timeout`
 
 ```
-Type:           decimal number
+Type:           duration
 Default:        OS default
 ```
 
-*Driver* side connection timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*. To set a server side timeout, use the parameter [`wait_timeout`](http://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_wait_timeout).
+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`
@@ -286,28 +332,36 @@ Valid Values:   true, false, skip-verify, <name>
 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`](http://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig).
+`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`
 
 ```
-Type:           decimal number
+Type:           duration
 Default:        0
 ```
 
-I/O write timeout. The value must be a decimal number with an unit suffix ( *"ms"*, *"s"*, *"m"*, *"h"* ), such as *"30s"*, *"0.5m"* or *"1m30s"*.
+I/O write timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*.
 
 
 ##### System Variables
 
-All other parameters are interpreted as system variables:
-  * `autocommit`: `"SET autocommit=<value>"`
-  * [`time_zone`](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html): `"SET time_zone=<value>"`
-  * [`tx_isolation`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `"SET tx_isolation=<value>"`
-  * `param`: `"SET <param>=<value>"`
+Any other parameters are interpreted as system variables:
+  * `<boolean_var>=<value>`: `SET <boolean_var>=<value>`
+  * `<enum_var>=<value>`: `SET <enum_var>=<value>`
+  * `<string_var>=%27<value>%27`: `SET <string_var>='<value>'`
+
+Rules:
+* 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`).
+
+Examples:
+  * `autocommit=1`: `SET autocommit=1`
+  * [`time_zone=%27Europe%2FParis%27`](https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html): `SET time_zone='Europe/Paris'`
+  * [`tx_isolation=%27REPEATABLE-READ%27`](https://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tx_isolation): `SET tx_isolation='REPEATABLE-READ'`
 
-*The values must be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed!*
 
 #### Examples
 ```
@@ -322,9 +376,9 @@ root:pw@unix(/tmp/mysql.sock)/myDatabase?loc=Local
 user:password@tcp(localhost:5555)/dbname?tls=skip-verify&autocommit=true
 ```
 
-Use the [strict mode](#strict) but ignore notes:
+Treat warnings as errors by setting the system variable [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html):
 ```
-user:password@/dbname?strict=true&sql_notes=false
+user:password@/dbname?sql_mode=TRADITIONAL
 ```
 
 TCP via IPv6:
@@ -337,11 +391,16 @@ TCP on a remote host, e.g. Amazon RDS:
 id:password@tcp(your-amazonaws-uri.com:3306)/dbname
 ```
 
-Google Cloud SQL on App Engine:
+Google Cloud SQL on App Engine (First Generation MySQL Server):
 ```
 user@cloudsql(project-id:instance-name)/dbname
 ```
 
+Google Cloud SQL on App Engine (Second Generation MySQL Server):
+```
+user@cloudsql(project-id:regionname:instance-name)/dbname
+```
+
 TCP using default port (3306) on localhost:
 ```
 user:password@tcp/dbname?charset=utf8mb4,utf8&sys_var=esc%40ped
@@ -357,6 +416,18 @@ No Database preselected:
 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 `_`):
 ```go
@@ -367,17 +438,17 @@ Files must be whitelisted by registering them with `mysql.RegisterLocalFile(file
 
 To use a `io.Reader` a handler function must be registered with `mysql.RegisterReaderHandler(name, handler)` which returns a `io.Reader` or `io.ReadCloser`. The Reader is available with the filepath `Reader::<name>` then. Choose different names for different handlers and `DeregisterReaderHandler` when you don't need it anymore.
 
-See the [godoc of Go-MySQL-Driver](http://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details.
+See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details.
 
 
 ### `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](http://golang.org/pkg/time/#Location) with the `loc` DSN parameter.
+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.
 
 **Caution:** As of Go 1.1, this makes `time.Time` the only variable type you can scan `DATE` and `DATETIME` values into. This breaks for example [`sql.RawBytes` support](https://github.com/go-sql-driver/mysql/wiki/Examples#rawbytes).
 
-Alternatively you can use the [`NullTime`](http://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`.
+Alternatively you can use the [`NullTime`](https://godoc.org/github.com/go-sql-driver/mysql#NullTime) type as the scan destination, which works with both `time.Time` and `string` / `[]byte`.
 
 
 ### Unicode support
@@ -389,7 +460,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.
 
@@ -408,13 +478,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](http://www.mozilla.org/MPL/2.0/FAQ.html) if you have further questions regarding the license.
+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).
 
 ![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow")
 

+ 1 - 1
vendor/github.com/go-sql-driver/mysql/appengine.go

@@ -11,7 +11,7 @@
 package mysql
 
 import (
-	"appengine/cloudsql"
+	"google.golang.org/appengine/cloudsql"
 )
 
 func init() {

+ 420 - 0
vendor/github.com/go-sql-driver/mysql/auth.go

@@ -0,0 +1,420 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2018 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 (
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/x509"
+	"encoding/pem"
+	"sync"
+)
+
+// server pub keys registry
+var (
+	serverPubKeyLock     sync.RWMutex
+	serverPubKeyRegistry map[string]*rsa.PublicKey
+)
+
+// RegisterServerPubKey registers a server RSA public key which can be used to
+// send data in a secure manner to the server without receiving the public key
+// in a potentially insecure way from the server first.
+// Registered keys can afterwards be used adding serverPubKey=<name> to the DSN.
+//
+// Note: The provided rsa.PublicKey instance is exclusively owned by the driver
+// after registering it and may not be modified.
+//
+//  data, err := ioutil.ReadFile("mykey.pem")
+//  if err != nil {
+//  	log.Fatal(err)
+//  }
+//
+//  block, _ := pem.Decode(data)
+//  if block == nil || block.Type != "PUBLIC KEY" {
+//  	log.Fatal("failed to decode PEM block containing public key")
+//  }
+//
+//  pub, err := x509.ParsePKIXPublicKey(block.Bytes)
+//  if err != nil {
+//  	log.Fatal(err)
+//  }
+//
+//  if rsaPubKey, ok := pub.(*rsa.PublicKey); ok {
+//  	mysql.RegisterServerPubKey("mykey", rsaPubKey)
+//  } else {
+//  	log.Fatal("not a RSA public key")
+//  }
+//
+func RegisterServerPubKey(name string, pubKey *rsa.PublicKey) {
+	serverPubKeyLock.Lock()
+	if serverPubKeyRegistry == nil {
+		serverPubKeyRegistry = make(map[string]*rsa.PublicKey)
+	}
+
+	serverPubKeyRegistry[name] = pubKey
+	serverPubKeyLock.Unlock()
+}
+
+// DeregisterServerPubKey removes the public key registered with the given name.
+func DeregisterServerPubKey(name string) {
+	serverPubKeyLock.Lock()
+	if serverPubKeyRegistry != nil {
+		delete(serverPubKeyRegistry, name)
+	}
+	serverPubKeyLock.Unlock()
+}
+
+func getServerPubKey(name string) (pubKey *rsa.PublicKey) {
+	serverPubKeyLock.RLock()
+	if v, ok := serverPubKeyRegistry[name]; ok {
+		pubKey = v
+	}
+	serverPubKeyLock.RUnlock()
+	return
+}
+
+// Hash password using pre 4.1 (old password) method
+// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
+type myRnd struct {
+	seed1, seed2 uint32
+}
+
+const myRndMaxVal = 0x3FFFFFFF
+
+// Pseudo random number generator
+func newMyRnd(seed1, seed2 uint32) *myRnd {
+	return &myRnd{
+		seed1: seed1 % myRndMaxVal,
+		seed2: seed2 % myRndMaxVal,
+	}
+}
+
+// Tested to be equivalent to MariaDB's floating point variant
+// http://play.golang.org/p/QHvhd4qved
+// http://play.golang.org/p/RG0q4ElWDx
+func (r *myRnd) NextByte() byte {
+	r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
+	r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
+
+	return byte(uint64(r.seed1) * 31 / myRndMaxVal)
+}
+
+// Generate binary hash from byte string using insecure pre 4.1 method
+func pwHash(password []byte) (result [2]uint32) {
+	var add uint32 = 7
+	var tmp uint32
+
+	result[0] = 1345345333
+	result[1] = 0x12345671
+
+	for _, c := range password {
+		// skip spaces and tabs in password
+		if c == ' ' || c == '\t' {
+			continue
+		}
+
+		tmp = uint32(c)
+		result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
+		result[1] += (result[1] << 8) ^ result[0]
+		add += tmp
+	}
+
+	// Remove sign bit (1<<31)-1)
+	result[0] &= 0x7FFFFFFF
+	result[1] &= 0x7FFFFFFF
+
+	return
+}
+
+// Hash password using insecure pre 4.1 method
+func scrambleOldPassword(scramble []byte, password string) []byte {
+	if len(password) == 0 {
+		return nil
+	}
+
+	scramble = scramble[:8]
+
+	hashPw := pwHash([]byte(password))
+	hashSc := pwHash(scramble)
+
+	r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
+
+	var out [8]byte
+	for i := range out {
+		out[i] = r.NextByte() + 64
+	}
+
+	mask := r.NextByte()
+	for i := range out {
+		out[i] ^= mask
+	}
+
+	return out[:]
+}
+
+// Hash password using 4.1+ method (SHA1)
+func scramblePassword(scramble []byte, password string) []byte {
+	if len(password) == 0 {
+		return nil
+	}
+
+	// stage1Hash = SHA1(password)
+	crypt := sha1.New()
+	crypt.Write([]byte(password))
+	stage1 := crypt.Sum(nil)
+
+	// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
+	// inner Hash
+	crypt.Reset()
+	crypt.Write(stage1)
+	hash := crypt.Sum(nil)
+
+	// outer Hash
+	crypt.Reset()
+	crypt.Write(scramble)
+	crypt.Write(hash)
+	scramble = crypt.Sum(nil)
+
+	// token = scrambleHash XOR stage1Hash
+	for i := range scramble {
+		scramble[i] ^= stage1[i]
+	}
+	return scramble
+}
+
+// Hash password using MySQL 8+ method (SHA256)
+func scrambleSHA256Password(scramble []byte, password string) []byte {
+	if len(password) == 0 {
+		return nil
+	}
+
+	// XOR(SHA256(password), SHA256(SHA256(SHA256(password)), scramble))
+
+	crypt := sha256.New()
+	crypt.Write([]byte(password))
+	message1 := crypt.Sum(nil)
+
+	crypt.Reset()
+	crypt.Write(message1)
+	message1Hash := crypt.Sum(nil)
+
+	crypt.Reset()
+	crypt.Write(message1Hash)
+	crypt.Write(scramble)
+	message2 := crypt.Sum(nil)
+
+	for i := range message1 {
+		message1[i] ^= message2[i]
+	}
+
+	return message1
+}
+
+func encryptPassword(password string, seed []byte, pub *rsa.PublicKey) ([]byte, error) {
+	plain := make([]byte, len(password)+1)
+	copy(plain, password)
+	for i := range plain {
+		j := i % len(seed)
+		plain[i] ^= seed[j]
+	}
+	sha1 := sha1.New()
+	return rsa.EncryptOAEP(sha1, rand.Reader, pub, plain, nil)
+}
+
+func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) error {
+	enc, err := encryptPassword(mc.cfg.Passwd, seed, pub)
+	if err != nil {
+		return err
+	}
+	return mc.writeAuthSwitchPacket(enc, false)
+}
+
+func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
+	switch plugin {
+	case "caching_sha2_password":
+		authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
+		return authResp, (authResp == nil), nil
+
+	case "mysql_old_password":
+		if !mc.cfg.AllowOldPasswords {
+			return nil, false, ErrOldPassword
+		}
+		// Note: there are edge cases where this should work but doesn't;
+		// this is currently "wontfix":
+		// https://github.com/go-sql-driver/mysql/issues/184
+		authResp := scrambleOldPassword(authData[:8], mc.cfg.Passwd)
+		return authResp, true, nil
+
+	case "mysql_clear_password":
+		if !mc.cfg.AllowCleartextPasswords {
+			return nil, false, ErrCleartextPassword
+		}
+		// 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
+		return []byte(mc.cfg.Passwd), true, nil
+
+	case "mysql_native_password":
+		if !mc.cfg.AllowNativePasswords {
+			return nil, false, ErrNativePassword
+		}
+		// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
+		// Native password authentication only need and will need 20-byte challenge.
+		authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
+		return authResp, false, nil
+
+	case "sha256_password":
+		if len(mc.cfg.Passwd) == 0 {
+			return nil, true, nil
+		}
+		if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
+			// write cleartext auth packet
+			return []byte(mc.cfg.Passwd), true, nil
+		}
+
+		pubKey := mc.cfg.pubKey
+		if pubKey == nil {
+			// request public key from server
+			return []byte{1}, false, nil
+		}
+
+		// encrypted password
+		enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
+		return enc, false, err
+
+	default:
+		errLog.Print("unknown auth plugin:", plugin)
+		return nil, false, ErrUnknownPlugin
+	}
+}
+
+func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
+	// Read Result Packet
+	authData, newPlugin, err := mc.readAuthResult()
+	if err != nil {
+		return err
+	}
+
+	// handle auth plugin switch, if requested
+	if newPlugin != "" {
+		// If CLIENT_PLUGIN_AUTH capability is not supported, no new cipher is
+		// sent and we have to keep using the cipher sent in the init packet.
+		if authData == nil {
+			authData = oldAuthData
+		} else {
+			// copy data from read buffer to owned slice
+			copy(oldAuthData, authData)
+		}
+
+		plugin = newPlugin
+
+		authResp, addNUL, err := mc.auth(authData, plugin)
+		if err != nil {
+			return err
+		}
+		if err = mc.writeAuthSwitchPacket(authResp, addNUL); err != nil {
+			return err
+		}
+
+		// Read Result Packet
+		authData, newPlugin, err = mc.readAuthResult()
+		if err != nil {
+			return err
+		}
+
+		// Do not allow to change the auth plugin more than once
+		if newPlugin != "" {
+			return ErrMalformPkt
+		}
+	}
+
+	switch plugin {
+
+	// https://insidemysql.com/preparing-your-community-connector-for-mysql-8-part-2-sha256/
+	case "caching_sha2_password":
+		switch len(authData) {
+		case 0:
+			return nil // auth successful
+		case 1:
+			switch authData[0] {
+			case cachingSha2PasswordFastAuthSuccess:
+				if err = mc.readResultOK(); err == nil {
+					return nil // auth successful
+				}
+
+			case cachingSha2PasswordPerformFullAuthentication:
+				if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
+					// write cleartext auth packet
+					err = mc.writeAuthSwitchPacket([]byte(mc.cfg.Passwd), true)
+					if err != nil {
+						return err
+					}
+				} else {
+					pubKey := mc.cfg.pubKey
+					if pubKey == nil {
+						// request public key from server
+						data := mc.buf.takeSmallBuffer(4 + 1)
+						data[4] = cachingSha2PasswordRequestPublicKey
+						mc.writePacket(data)
+
+						// parse public key
+						data, err := mc.readPacket()
+						if err != nil {
+							return err
+						}
+
+						block, _ := pem.Decode(data[1:])
+						pkix, err := x509.ParsePKIXPublicKey(block.Bytes)
+						if err != nil {
+							return err
+						}
+						pubKey = pkix.(*rsa.PublicKey)
+					}
+
+					// send encrypted password
+					err = mc.sendEncryptedPassword(oldAuthData, pubKey)
+					if err != nil {
+						return err
+					}
+				}
+				return mc.readResultOK()
+
+			default:
+				return ErrMalformPkt
+			}
+		default:
+			return ErrMalformPkt
+		}
+
+	case "sha256_password":
+		switch len(authData) {
+		case 0:
+			return nil // auth successful
+		default:
+			block, _ := pem.Decode(authData)
+			pub, err := x509.ParsePKIXPublicKey(block.Bytes)
+			if err != nil {
+				return err
+			}
+
+			// send encrypted password
+			err = mc.sendEncryptedPassword(oldAuthData, pub.(*rsa.PublicKey))
+			if err != nil {
+				return err
+			}
+			return mc.readResultOK()
+		}
+
+	default:
+		return nil // auth successful
+	}
+
+	return err
+}

+ 6 - 6
vendor/github.com/go-sql-driver/mysql/buffer.go

@@ -130,18 +130,18 @@ func (b *buffer) takeBuffer(length int) []byte {
 // smaller than defaultBufSize
 // Only one buffer (total) can be used at a time.
 func (b *buffer) takeSmallBuffer(length int) []byte {
-	if b.length == 0 {
-		return b.buf[:length]
+	if b.length > 0 {
+		return nil
 	}
-	return nil
+	return b.buf[:length]
 }
 
 // takeCompleteBuffer returns the complete existing buffer.
 // This can be used if the necessary buffer size is unknown.
 // Only one buffer (total) can be used at a time.
 func (b *buffer) takeCompleteBuffer() []byte {
-	if b.length == 0 {
-		return b.buf
+	if b.length > 0 {
+		return nil
 	}
-	return nil
+	return b.buf
 }

+ 1 - 0
vendor/github.com/go-sql-driver/mysql/collations.go

@@ -9,6 +9,7 @@
 package mysql
 
 const defaultCollation = "utf8_general_ci"
+const binaryCollation = "binary"
 
 // A list of available collations mapped to the internal ID.
 // To update this map use the following MySQL query:

+ 123 - 34
vendor/github.com/go-sql-driver/mysql/connection.go

@@ -10,26 +10,44 @@ package mysql
 
 import (
 	"database/sql/driver"
+	"io"
 	"net"
 	"strconv"
 	"strings"
 	"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
 	affectedRows     uint64
 	insertId         uint64
 	cfg              *Config
-	maxPacketAllowed int
+	maxAllowedPacket int
 	maxWriteSize     int
 	writeTimeout     time.Duration
 	flags            clientFlag
 	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
@@ -62,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)
 	}
 
@@ -91,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{
@@ -135,11 +185,16 @@ func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
 }
 
 func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (string, error) {
+	// Number of ? should be same to len(args)
+	if strings.Count(query, "?") != len(args) {
+		return "", driver.ErrSkip
+	}
+
 	buf := mc.buf.takeCompleteBuffer()
 	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
@@ -241,7 +296,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
 			return "", driver.ErrSkip
 		}
 
-		if len(buf)+4 > mc.maxPacketAllowed {
+		if len(buf)+4 > mc.maxAllowedPacket {
 			return "", driver.ErrSkip
 		}
 	}
@@ -252,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
 	}
@@ -266,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
@@ -278,32 +332,43 @@ 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
-	err := mc.writeCommandPacketStr(comQuery, query)
-	if err != nil {
-		return err
+	if err := mc.writeCommandPacketStr(comQuery, query); err != nil {
+		return mc.markBadConn(err)
 	}
 
 	// Read Result
 	resLen, err := mc.readResultSetHeaderPacket()
-	if err == nil && resLen > 0 {
-		if err = mc.readUntilEOF(); err != nil {
+	if err != nil {
+		return err
+	}
+
+	if resLen > 0 {
+		// columns
+		if err := mc.readUntilEOF(); err != nil {
 			return err
 		}
 
-		err = mc.readUntilEOF()
+		// rows
+		if err := mc.readUntilEOF(); err != nil {
+			return err
+		}
 	}
 
-	return err
+	return mc.discardResults()
 }
 
 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
 	}
@@ -317,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)
@@ -330,15 +394,22 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro
 			rows.mc = mc
 
 			if resLen == 0 {
-				// no columns, no more data
-				return emptyRows{}, nil
+				rows.rs.done = true
+
+				switch err := rows.NextResultSet(); err {
+				case nil, io.EOF:
+					return rows, nil
+				default:
+					return nil, err
+				}
 			}
+
 			// Columns
-			rows.columns, err = mc.readColumns(resLen)
+			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
@@ -354,7 +425,7 @@ func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
 	if err == nil {
 		rows := new(textRows)
 		rows.mc = mc
-		rows.columns = []mysqlField{{fieldType: fieldTypeVarChar}}
+		rows.rs.columns = []mysqlField{{fieldType: fieldTypeVarChar}}
 
 		if resLen > 0 {
 			// Columns
@@ -370,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:
+	}
+}

+ 208 - 0
vendor/github.com/go-sql-driver/mysql/connection_go18.go

@@ -0,0 +1,208 @@
+// 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
+}

+ 18 - 7
vendor/github.com/go-sql-driver/mysql/const.go

@@ -9,7 +9,9 @@
 package mysql
 
 const (
-	minProtocolVersion byte = 10
+	defaultAuthPlugin       = "mysql_native_password"
+	defaultMaxAllowedPacket = 4 << 20 // 4 MiB
+	minProtocolVersion      = 10
 	maxPacketSize           = 1<<24 - 1
 	timeFormat              = "2006-01-02 15:04:05.999999"
 )
@@ -18,10 +20,11 @@ const (
 // http://dev.mysql.com/doc/internals/en/client-server-protocol.html
 
 const (
-	iOK          byte = 0x00
-	iLocalInFile byte = 0xfb
-	iEOF         byte = 0xfe
-	iERR         byte = 0xff
+	iOK           byte = 0x00
+	iAuthMoreData byte = 0x01
+	iLocalInFile  byte = 0xfb
+	iEOF          byte = 0xfe
+	iERR          byte = 0xff
 )
 
 // https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags
@@ -87,8 +90,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 +112,7 @@ const (
 	fieldTypeBit
 )
 const (
-	fieldTypeJSON byte = iota + 0xf5
+	fieldTypeJSON fieldType = iota + 0xf5
 	fieldTypeNewDecimal
 	fieldTypeEnum
 	fieldTypeSet
@@ -161,3 +166,9 @@ const (
 	statusInTransReadonly
 	statusSessionStateChanged
 )
+
+const (
+	cachingSha2PasswordRequestPublicKey          = 2
+	cachingSha2PasswordFastAuthSuccess           = 3
+	cachingSha2PasswordPerformFullAuthentication = 4
+)

+ 50 - 48
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:
 //
@@ -20,8 +20,14 @@ import (
 	"database/sql"
 	"database/sql/driver"
 	"net"
+	"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.
 // In general the driver is used via the database/sql package.
 type MySQLDriver struct{}
@@ -30,12 +36,17 @@ type MySQLDriver struct{}
 // Custom dial functions must be registered with RegisterDial
 type DialFunc func(addr string) (net.Conn, error)
 
-var dials map[string]DialFunc
+var (
+	dialsLock sync.RWMutex
+	dials     map[string]DialFunc
+)
 
 // RegisterDial registers a custom dial function. It can then be used by the
 // network address mynet(addr), where mynet is the registered new network.
 // addr is passed as a parameter to the dial function.
 func RegisterDial(net string, dial DialFunc) {
+	dialsLock.Lock()
+	defer dialsLock.Unlock()
 	if dials == nil {
 		dials = make(map[string]DialFunc)
 	}
@@ -50,18 +61,21 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 
 	// New mysqlConn
 	mc := &mysqlConn{
-		maxPacketAllowed: maxPacketSize,
+		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 {
+	dialsLock.RLock()
+	dial, ok := dials[mc.cfg.Net]
+	dialsLock.RUnlock()
+	if ok {
 		mc.netConn, err = dial(mc.cfg.Addr)
 	} else {
 		nd := net.Dialer{Timeout: mc.cfg.Timeout}
@@ -81,6 +95,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
@@ -88,20 +107,31 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 	mc.writeTimeout = mc.cfg.WriteTimeout
 
 	// Reading Handshake Initialization Packet
-	cipher, err := mc.readInitPacket()
+	authData, plugin, err := mc.readHandshakePacket()
 	if err != nil {
 		mc.cleanup()
 		return nil, err
 	}
 
 	// Send Client Authentication Packet
-	if err = mc.writeAuthPacket(cipher); err != nil {
+	authResp, addNUL, err := mc.auth(authData, plugin)
+	if err != nil {
+		// try the default auth plugin, if using the requested plugin failed
+		errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
+		plugin = defaultAuthPlugin
+		authResp, addNUL, err = mc.auth(authData, plugin)
+		if err != nil {
+			mc.cleanup()
+			return nil, err
+		}
+	}
+	if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
 		mc.cleanup()
 		return nil, err
 	}
 
 	// Handle response to auth packet, switch methods if possible
-	if err = handleAuthResult(mc, cipher); err != nil {
+	if err = mc.handleAuthResult(authData, plugin); err != nil {
 		// Authentication failed and MySQL has already closed the connection
 		// (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
 		// Do not send COM_QUIT, just cleanup and return the error.
@@ -109,15 +139,19 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 		return nil, err
 	}
 
-	// Get max allowed packet size
-	maxap, err := mc.getSystemVar("max_allowed_packet")
-	if err != nil {
-		mc.Close()
-		return nil, err
+	if mc.cfg.MaxAllowedPacket > 0 {
+		mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket
+	} else {
+		// Get max allowed packet size
+		maxap, err := mc.getSystemVar("max_allowed_packet")
+		if err != nil {
+			mc.Close()
+			return nil, err
+		}
+		mc.maxAllowedPacket = stringToInt(maxap) - 1
 	}
-	mc.maxPacketAllowed = stringToInt(maxap) - 1
-	if mc.maxPacketAllowed < maxPacketSize {
-		mc.maxWriteSize = mc.maxPacketAllowed
+	if mc.maxAllowedPacket < maxPacketSize {
+		mc.maxWriteSize = mc.maxAllowedPacket
 	}
 
 	// Handle DSN Params
@@ -130,38 +164,6 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
 	return mc, nil
 }
 
-func handleAuthResult(mc *mysqlConn, cipher []byte) error {
-	// Read Result Packet
-	err := mc.readResultOK()
-	if err == nil {
-		return nil // auth successful
-	}
-
-	if mc.cfg == nil {
-		return err // auth failed and retry not possible
-	}
-
-	// Retry auth if configured to do so.
-	if mc.cfg.AllowOldPasswords && err == ErrOldPassword {
-		// Retry with old authentication method. Note: there are edge cases
-		// where this should work but doesn't; this is currently "wontfix":
-		// https://github.com/go-sql-driver/mysql/issues/184
-		if err = mc.writeOldAuthPacket(cipher); err != nil {
-			return err
-		}
-		err = mc.readResultOK()
-	} else if mc.cfg.AllowCleartextPasswords && err == ErrCleartextPassword {
-		// Retry with clear text password for
-		// 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
-		if err = mc.writeClearAuthPacket(); err != nil {
-			return err
-		}
-		err = mc.readResultOK()
-	}
-	return err
-}
-
 func init() {
 	sql.Register("mysql", &MySQLDriver{})
 }

+ 156 - 58
vendor/github.com/go-sql-driver/mysql/dsn.go

@@ -10,11 +10,14 @@ package mysql
 
 import (
 	"bytes"
+	"crypto/rsa"
 	"crypto/tls"
 	"errors"
 	"fmt"
 	"net"
 	"net/url"
+	"sort"
+	"strconv"
 	"strings"
 	"time"
 )
@@ -26,31 +29,84 @@ 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)
-	Net          string            // Network type
-	Addr         string            // Network address (requires Net)
-	DBName       string            // Database name
-	Params       map[string]string // Connection parameters
-	Collation    string            // Connection collation
-	Loc          *time.Location    // Location for time.Time values
-	TLSConfig    string            // TLS configuration name
-	tls          *tls.Config       // TLS configuration
-	Timeout      time.Duration     // Dial timeout
-	ReadTimeout  time.Duration     // I/O read timeout
-	WriteTimeout time.Duration     // I/O write timeout
+	User             string            // Username
+	Passwd           string            // Password (requires User)
+	Net              string            // Network type
+	Addr             string            // Network address (requires Net)
+	DBName           string            // Database name
+	Params           map[string]string // Connection parameters
+	Collation        string            // Connection collation
+	Loc              *time.Location    // Location for time.Time values
+	MaxAllowedPacket int               // Max packet size allowed
+	ServerPubKey     string            // Server public key name
+	pubKey           *rsa.PublicKey    // Server public key
+	TLSConfig        string            // TLS configuration name
+	tls              *tls.Config       // TLS configuration
+	Timeout          time.Duration     // Dial timeout
+	ReadTimeout      time.Duration     // I/O read timeout
+	WriteTimeout     time.Duration     // I/O write timeout
 
 	AllowAllFiles           bool // Allow all files to be used with LOAD DATA LOCAL INFILE
 	AllowCleartextPasswords bool // Allows the cleartext client side plugin
+	AllowNativePasswords    bool // Allows the native password authentication method
 	AllowOldPasswords       bool // Allows the old insecure password method
 	ClientFoundRows         bool // Return number of matching rows instead of rows changed
 	ColumnsWithAlias        bool // Prepend table alias to column names
 	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)
+	}
+
+	if cfg.tls != nil {
+		if cfg.tls.ServerName == "" && !cfg.tls.InsecureSkipVerify {
+			host, _, err := net.SplitHostPort(cfg.Addr)
+			if err == nil {
+				cfg.tls.ServerName = host
+			}
+		}
+	}
+
+	return nil
 }
 
 // FormatDSN formats the given Config into a DSN string which can be passed to
@@ -99,6 +155,15 @@ func (cfg *Config) FormatDSN() string {
 		}
 	}
 
+	if !cfg.AllowNativePasswords {
+		if hasParam {
+			buf.WriteString("&allowNativePasswords=false")
+		} else {
+			hasParam = true
+			buf.WriteString("?allowNativePasswords=false")
+		}
+	}
+
 	if cfg.AllowOldPasswords {
 		if hasParam {
 			buf.WriteString("&allowOldPasswords=true")
@@ -183,13 +248,23 @@ func (cfg *Config) FormatDSN() string {
 		buf.WriteString(cfg.ReadTimeout.String())
 	}
 
-	if cfg.Strict {
+	if cfg.RejectReadOnly {
+		if hasParam {
+			buf.WriteString("&rejectReadOnly=true")
+		} else {
+			hasParam = true
+			buf.WriteString("?rejectReadOnly=true")
+		}
+	}
+
+	if len(cfg.ServerPubKey) > 0 {
 		if hasParam {
-			buf.WriteString("&strict=true")
+			buf.WriteString("&serverPubKey=")
 		} else {
 			hasParam = true
-			buf.WriteString("?strict=true")
+			buf.WriteString("?serverPubKey=")
 		}
+		buf.WriteString(url.QueryEscape(cfg.ServerPubKey))
 	}
 
 	if cfg.Timeout > 0 {
@@ -222,9 +297,25 @@ func (cfg *Config) FormatDSN() string {
 		buf.WriteString(cfg.WriteTimeout.String())
 	}
 
+	if cfg.MaxAllowedPacket != defaultMaxAllowedPacket {
+		if hasParam {
+			buf.WriteString("&maxAllowedPacket=")
+		} else {
+			hasParam = true
+			buf.WriteString("?maxAllowedPacket=")
+		}
+		buf.WriteString(strconv.Itoa(cfg.MaxAllowedPacket))
+
+	}
+
 	// 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 {
@@ -234,7 +325,7 @@ func (cfg *Config) FormatDSN() string {
 
 			buf.WriteString(param)
 			buf.WriteByte('=')
-			buf.WriteString(url.QueryEscape(value))
+			buf.WriteString(url.QueryEscape(cfg.Params[param]))
 		}
 	}
 
@@ -244,10 +335,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&paramN=valueN]
 	// Find the last '/' (since the password or the net addr might contain a '/')
@@ -315,28 +403,9 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
 		return nil, errInvalidDSNNoSlash
 	}
 
-	if cfg.InterpolateParams && unsafeCollations[cfg.Collation] {
-		return nil, 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 nil, errors.New("default addr for network '" + cfg.Net + "' unknown")
-		}
-
+	if err = cfg.normalize(); err != nil {
+		return nil, err
 	}
-
 	return
 }
 
@@ -351,7 +420,6 @@ func parseDSNParams(cfg *Config, params string) (err error) {
 
 		// cfg params
 		switch value := param[1]; param[0] {
-
 		// Disable INFILE whitelist / enable all files
 		case "allowAllFiles":
 			var isBool bool
@@ -368,6 +436,14 @@ func parseDSNParams(cfg *Config, params string) (err error) {
 				return errors.New("invalid bool value: " + value)
 			}
 
+		// Use native password authentication
+		case "allowNativePasswords":
+			var isBool bool
+			cfg.AllowNativePasswords, isBool = readBool(value)
+			if !isBool {
+				return errors.New("invalid bool value: " + value)
+			}
+
 		// Use old authentication mode (pre MySQL 4.1)
 		case "allowOldPasswords":
 			var isBool bool
@@ -441,14 +517,32 @@ 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)
 			}
 
+		// Server public key
+		case "serverPubKey":
+			name, err := url.QueryUnescape(value)
+			if err != nil {
+				return fmt.Errorf("invalid value for server pub key name: %v", err)
+			}
+
+			if pubKey := getServerPubKey(name); pubKey != nil {
+				cfg.ServerPubKey = name
+				cfg.pubKey = pubKey
+			} else {
+				return errors.New("invalid value / unknown server pub key name: " + name)
+			}
+
+		// 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)
@@ -475,14 +569,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 len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
-						host, _, err := net.SplitHostPort(cfg.Addr)
-						if err == nil {
-							tlsConfig.ServerName = host
-						}
-					}
-
+				if tlsConfig := getTLSConfigClone(name); tlsConfig != nil {
 					cfg.TLSConfig = name
 					cfg.tls = tlsConfig
 				} else {
@@ -496,7 +583,11 @@ func parseDSNParams(cfg *Config, params string) (err error) {
 			if err != nil {
 				return
 			}
-
+		case "maxAllowedPacket":
+			cfg.MaxAllowedPacket, err = strconv.Atoi(value)
+			if err != nil {
+				return
+			}
 		default:
 			// lazy init
 			if cfg.Params == nil {
@@ -511,3 +602,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
+}

+ 8 - 74
vendor/github.com/go-sql-driver/mysql/errors.go

@@ -9,10 +9,8 @@
 package mysql
 
 import (
-	"database/sql/driver"
 	"errors"
 	"fmt"
-	"io"
 	"log"
 	"os"
 )
@@ -22,14 +20,21 @@ var (
 	ErrInvalidConn       = errors.New("invalid connection")
 	ErrMalformPkt        = errors.New("malformed packet")
 	ErrNoTLS             = errors.New("TLS requested but server does not support TLS")
-	ErrOldPassword       = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
 	ErrCleartextPassword = errors.New("this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN")
+	ErrNativePassword    = errors.New("this user requires mysql native password authentication.")
+	ErrOldPassword       = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
 	ErrUnknownPlugin     = errors.New("this authentication plugin is not supported")
 	ErrOldProtocol       = errors.New("MySQL server does not support required protocol 41+")
 	ErrPktSync           = errors.New("commands out of sync. You can't run this command now")
 	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))
@@ -58,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
-		}
-	}
-}

+ 194 - 0
vendor/github.com/go-sql-driver/mysql/fields.go

@@ -0,0 +1,194 @@
+// 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"
+)
+
+func (mf *mysqlField) typeDatabaseName() string {
+	switch mf.fieldType {
+	case fieldTypeBit:
+		return "BIT"
+	case fieldTypeBLOB:
+		if mf.charSet != collations[binaryCollation] {
+			return "TEXT"
+		}
+		return "BLOB"
+	case fieldTypeDate:
+		return "DATE"
+	case fieldTypeDateTime:
+		return "DATETIME"
+	case fieldTypeDecimal:
+		return "DECIMAL"
+	case fieldTypeDouble:
+		return "DOUBLE"
+	case fieldTypeEnum:
+		return "ENUM"
+	case fieldTypeFloat:
+		return "FLOAT"
+	case fieldTypeGeometry:
+		return "GEOMETRY"
+	case fieldTypeInt24:
+		return "MEDIUMINT"
+	case fieldTypeJSON:
+		return "JSON"
+	case fieldTypeLong:
+		return "INT"
+	case fieldTypeLongBLOB:
+		if mf.charSet != collations[binaryCollation] {
+			return "LONGTEXT"
+		}
+		return "LONGBLOB"
+	case fieldTypeLongLong:
+		return "BIGINT"
+	case fieldTypeMediumBLOB:
+		if mf.charSet != collations[binaryCollation] {
+			return "MEDIUMTEXT"
+		}
+		return "MEDIUMBLOB"
+	case fieldTypeNewDate:
+		return "DATE"
+	case fieldTypeNewDecimal:
+		return "DECIMAL"
+	case fieldTypeNULL:
+		return "NULL"
+	case fieldTypeSet:
+		return "SET"
+	case fieldTypeShort:
+		return "SMALLINT"
+	case fieldTypeString:
+		if mf.charSet == collations[binaryCollation] {
+			return "BINARY"
+		}
+		return "CHAR"
+	case fieldTypeTime:
+		return "TIME"
+	case fieldTypeTimestamp:
+		return "TIMESTAMP"
+	case fieldTypeTiny:
+		return "TINYINT"
+	case fieldTypeTinyBLOB:
+		if mf.charSet != collations[binaryCollation] {
+			return "TINYTEXT"
+		}
+		return "TINYBLOB"
+	case fieldTypeVarChar:
+		if mf.charSet == collations[binaryCollation] {
+			return "VARBINARY"
+		}
+		return "VARCHAR"
+	case fieldTypeVarString:
+		if mf.charSet == collations[binaryCollation] {
+			return "VARBINARY"
+		}
+		return "VARCHAR"
+	case fieldTypeYear:
+		return "YEAR"
+	default:
+		return ""
+	}
+}
+
+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
+	charSet   uint8
+}
+
+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
+	}
+}

+ 2 - 1
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 {

+ 234 - 179
vendor/github.com/go-sql-driver/mysql/packets.go

@@ -25,26 +25,23 @@ import (
 
 // Read packet to buffer 'data'
 func (mc *mysqlConn) readPacket() ([]byte, error) {
-	var payload []byte
+	var prevData []byte
 	for {
-		// Read packet header
+		// 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]
+		// packet length [24 bit]
 		pktLen := int(uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16)
 
-		if pktLen < 1 {
-			errLog.Print(ErrMalformPkt)
-			mc.Close()
-			return nil, driver.ErrBadConn
-		}
-
-		// Check Packet Sync [8 bit]
+		// check packet sync [8 bit]
 		if data[3] != mc.sequence {
 			if data[3] > mc.sequence {
 				return nil, ErrPktSyncMul
@@ -53,26 +50,41 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
 		}
 		mc.sequence++
 
-		// Read packet body [pktLen bytes]
+		// packets with length 0 terminate a previous packet which is a
+		// multiple of (2^24)−1 bytes long
+		if pktLen == 0 {
+			// there was no previous packet
+			if prevData == nil {
+				errLog.Print(ErrMalformPkt)
+				mc.Close()
+				return nil, ErrInvalidConn
+			}
+
+			return prevData, nil
+		}
+
+		// 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
 		}
 
-		isLastPacket := (pktLen < maxPacketSize)
+		// return data if this was the last packet
+		if pktLen < maxPacketSize {
+			// zero allocations for non-split packets
+			if prevData == nil {
+				return data, nil
+			}
 
-		// Zero allocations for non-splitting packets
-		if isLastPacket && payload == nil {
-			return data, nil
+			return append(prevData, data...), nil
 		}
 
-		payload = append(payload, data...)
-
-		if isLastPacket {
-			return payload, nil
-		}
+		prevData = append(prevData, data...)
 	}
 }
 
@@ -80,7 +92,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
 func (mc *mysqlConn) writePacket(data []byte) error {
 	pktLen := len(data) - 4
 
-	if pktLen > mc.maxPacketAllowed {
+	if pktLen > mc.maxAllowedPacket {
 		return ErrPktTooLarge
 	}
 
@@ -119,33 +131,47 @@ 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
 	}
 }
 
 /******************************************************************************
-*                           Initialisation Process                            *
+*                           Initialization Process                            *
 ******************************************************************************/
 
 // Handshake Initialization Packet
 // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
-func (mc *mysqlConn) readInitPacket() ([]byte, error) {
+func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
 	data, err := mc.readPacket()
 	if err != nil {
-		return nil, err
+		// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
+		// in connection initialization we don't risk retrying non-idempotent actions.
+		if err == ErrInvalidConn {
+			return nil, "", driver.ErrBadConn
+		}
+		return nil, "", err
 	}
 
 	if data[0] == iERR {
-		return nil, mc.handleErrorPacket(data)
+		return nil, "", mc.handleErrorPacket(data)
 	}
 
 	// protocol version [1 byte]
 	if data[0] < minProtocolVersion {
-		return nil, fmt.Errorf(
+		return nil, "", fmt.Errorf(
 			"unsupported protocol version %d. Version %d or higher is required",
 			data[0],
 			minProtocolVersion,
@@ -157,7 +183,7 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
 	pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4
 
 	// first part of the password cipher [8 bytes]
-	cipher := data[pos : pos+8]
+	authData := data[pos : pos+8]
 
 	// (filler) always 0x00 [1 byte]
 	pos += 8 + 1
@@ -165,13 +191,14 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
 	// capability flags (lower 2 bytes) [2 bytes]
 	mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
 	if mc.flags&clientProtocol41 == 0 {
-		return nil, ErrOldProtocol
+		return nil, "", ErrOldProtocol
 	}
 	if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
-		return nil, ErrNoTLS
+		return nil, "", ErrNoTLS
 	}
 	pos += 2
 
+	plugin := ""
 	if len(data) > pos {
 		// character set [1 byte]
 		// status flags [2 bytes]
@@ -192,32 +219,34 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
 		//
 		// The official Python library uses the fixed length 12
 		// which seems to work but technically could have a hidden bug.
-		cipher = append(cipher, data[pos:pos+12]...)
+		authData = append(authData, data[pos:pos+12]...)
+		pos += 13
 
-		// TODO: Verify string termination
 		// EOF if version (>= 5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2)
 		// \NUL otherwise
-		//
-		//if data[len(data)-1] == 0 {
-		//	return
-		//}
-		//return ErrMalformPkt
+		if end := bytes.IndexByte(data[pos:], 0x00); end != -1 {
+			plugin = string(data[pos : pos+end])
+		} else {
+			plugin = string(data[pos:])
+		}
 
 		// make a memory safe copy of the cipher slice
 		var b [20]byte
-		copy(b[:], cipher)
-		return b[:], nil
+		copy(b[:], authData)
+		return b[:], plugin, nil
 	}
 
+	plugin = defaultAuthPlugin
+
 	// make a memory safe copy of the cipher slice
 	var b [8]byte
-	copy(b[:], cipher)
-	return b[:], nil
+	copy(b[:], authData)
+	return b[:], plugin, nil
 }
 
 // Client Authentication Packet
 // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
-func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
+func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool, plugin string) error {
 	// Adjust client flags based on server support
 	clientFlags := clientProtocol41 |
 		clientSecureConn |
@@ -241,10 +270,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
 		clientFlags |= clientMultiStatements
 	}
 
-	// User Password
-	scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.Passwd))
+	// encode length of the auth plugin data
+	var authRespLEIBuf [9]byte
+	authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(len(authResp)))
+	if len(authRespLEI) > 1 {
+		// if the length can not be written in 1 byte, it must be written as a
+		// length encoded integer
+		clientFlags |= clientPluginAuthLenEncClientData
+	}
 
-	pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + 1 + len(scrambleBuff) + 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
 	if n := len(mc.cfg.DBName); n > 0 {
@@ -255,9 +293,9 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
 	// Calculate packet length and get buffer with that size
 	data := mc.buf.takeSmallBuffer(pktLen + 4)
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot take the buffer. Something must be wrong with the connection
 		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+		return errBadConnNoWrite
 	}
 
 	// ClientFlags [32 bit]
@@ -312,9 +350,13 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
 	data[pos] = 0x00
 	pos++
 
-	// ScrambleBuffer [length encoded integer]
-	data[pos] = byte(len(scrambleBuff))
-	pos += 1 + copy(data[pos+1:], scrambleBuff)
+	// Auth Data [length encoded integer]
+	pos += copy(data[pos:], authRespLEI)
+	pos += copy(data[pos:], authResp)
+	if addNUL {
+		data[pos] = 0x00
+		pos++
+	}
 
 	// Databasename [null terminated string]
 	if len(mc.cfg.DBName) > 0 {
@@ -323,51 +365,31 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
 		pos++
 	}
 
-	// Assume native client during response
-	pos += copy(data[pos:], "mysql_native_password")
+	pos += copy(data[pos:], plugin)
 	data[pos] = 0x00
 
 	// Send Auth packet
 	return mc.writePacket(data)
 }
 
-//  Client old authentication packet
 // 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))
-
-	// Calculate the packet length and add a tailing 0
-	pktLen := len(scrambleBuff) + 1
-	data := mc.buf.takeSmallBuffer(4 + pktLen)
-	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
-		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte, addNUL bool) error {
+	pktLen := 4 + len(authData)
+	if addNUL {
+		pktLen++
 	}
-
-	// Add the scrambled password [null terminated string]
-	copy(data[4:], scrambleBuff)
-	data[4+pktLen-1] = 0x00
-
-	return mc.writePacket(data)
-}
-
-//  Client clear text authentication packet
-// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
-func (mc *mysqlConn) writeClearAuthPacket() error {
-	// Calculate the packet length and add a tailing 0
-	pktLen := len(mc.cfg.Passwd) + 1
-	data := mc.buf.takeSmallBuffer(4 + pktLen)
+	data := mc.buf.takeSmallBuffer(pktLen)
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot 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]
-	copy(data[4:], mc.cfg.Passwd)
-	data[4+pktLen-1] = 0x00
+	// Add the auth data [EOF]
+	copy(data[4:], authData)
+	if addNUL {
+		data[pktLen-1] = 0x00
+	}
 
 	return mc.writePacket(data)
 }
@@ -382,9 +404,9 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
 
 	data := mc.buf.takeSmallBuffer(4 + 1)
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot take the buffer. Something must be wrong with the connection
 		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+		return errBadConnNoWrite
 	}
 
 	// Add command byte
@@ -401,9 +423,9 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
 	pktLen := 1 + len(arg)
 	data := mc.buf.takeBuffer(pktLen + 4)
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot take the buffer. Something must be wrong with the connection
 		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+		return errBadConnNoWrite
 	}
 
 	// Add command byte
@@ -422,9 +444,9 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
 
 	data := mc.buf.takeSmallBuffer(4 + 1 + 4)
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot take the buffer. Something must be wrong with the connection
 		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+		return errBadConnNoWrite
 	}
 
 	// Add command byte
@@ -444,37 +466,50 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
 *                              Result Packets                                 *
 ******************************************************************************/
 
-// Returns error if Packet is not an 'Result OK'-Packet
-func (mc *mysqlConn) readResultOK() error {
+func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
 	data, err := mc.readPacket()
-	if err == nil {
-		// packet indicator
-		switch data[0] {
+	if err != nil {
+		return nil, "", err
+	}
 
-		case iOK:
-			return mc.handleOkPacket(data)
+	// packet indicator
+	switch data[0] {
 
-		case iEOF:
-			if len(data) > 1 {
-				plugin := string(data[1:bytes.IndexByte(data, 0x00)])
-				if plugin == "mysql_old_password" {
-					// using old_passwords
-					return ErrOldPassword
-				} else if plugin == "mysql_clear_password" {
-					// using clear text password
-					return ErrCleartextPassword
-				} else {
-					return ErrUnknownPlugin
-				}
-			} else {
-				return ErrOldPassword
-			}
+	case iOK:
+		return nil, "", mc.handleOkPacket(data)
 
-		default: // Error otherwise
-			return mc.handleErrorPacket(data)
+	case iAuthMoreData:
+		return data[1:], "", err
+
+	case iEOF:
+		if len(data) < 1 {
+			// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
+			return nil, "mysql_old_password", nil
 		}
+		pluginEndIndex := bytes.IndexByte(data, 0x00)
+		if pluginEndIndex < 0 {
+			return nil, "", ErrMalformPkt
+		}
+		plugin := string(data[1:pluginEndIndex])
+		authData := data[pluginEndIndex+1:]
+		return authData, plugin, nil
+
+	default: // Error otherwise
+		return nil, "", mc.handleErrorPacket(data)
 	}
-	return err
+}
+
+// Returns error if Packet is not an 'Result OK'-Packet
+func (mc *mysqlConn) readResultOK() error {
+	data, err := mc.readPacket()
+	if err != nil {
+		return err
+	}
+
+	if data[0] == iOK {
+		return mc.handleOkPacket(data)
+	}
+	return mc.handleErrorPacket(data)
 }
 
 // Result Set Header Packet
@@ -517,6 +552,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]
@@ -551,19 +602,12 @@ func (mc *mysqlConn) handleOkPacket(data []byte) error {
 
 	// server_status [2 bytes]
 	mc.status = readStatus(data[1+n+m : 1+n+m+2])
-	if err := mc.discardResults(); err != nil {
-		return err
+	if mc.status&statusMoreResultsExists != 0 {
+		return nil
 	}
 
 	// 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
 }
 
@@ -635,14 +679,21 @@ func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {
 		if err != nil {
 			return nil, err
 		}
+		pos += n
 
 		// Filler [uint8]
+		pos++
+
 		// Charset [charset, collation uint8]
+		columns[i].charSet = data[pos]
+		pos += 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]
@@ -665,6 +716,10 @@ func (mc *mysqlConn) readColumns(count int) ([]mysqlField, error) {
 func (rows *textRows) readRow(dest []driver.Value) error {
 	mc := rows.mc
 
+	if rows.rs.done {
+		return io.EOF
+	}
+
 	data, err := mc.readPacket()
 	if err != nil {
 		return err
@@ -674,10 +729,10 @@ func (rows *textRows) readRow(dest []driver.Value) error {
 	if data[0] == iEOF && len(data) == 5 {
 		// server_status [2 bytes]
 		rows.mc.status = readStatus(data[3:])
-		if err := rows.mc.discardResults(); err != nil {
-			return err
+		rows.rs.done = true
+		if !rows.HasNextResultSet() {
+			rows.mc = nil
 		}
-		rows.mc = nil
 		return io.EOF
 	}
 	if data[0] == iERR {
@@ -699,7 +754,7 @@ func (rows *textRows) readRow(dest []driver.Value) error {
 				if !mc.parseTime {
 					continue
 				} else {
-					switch rows.columns[i].fieldType {
+					switch rows.rs.columns[i].fieldType {
 					case fieldTypeTimestamp, fieldTypeDateTime,
 						fieldTypeDate, fieldTypeNewDate:
 						dest[i], err = parseDateTime(
@@ -771,14 +826,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
@@ -786,7 +834,7 @@ func (stmt *mysqlStmt) readPrepareResultPacket() (uint16, error) {
 
 // http://dev.mysql.com/doc/internals/en/com-stmt-send-long-data.html
 func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
-	maxLen := stmt.mc.maxPacketAllowed - 1
+	maxLen := stmt.mc.maxAllowedPacket - 1
 	pktLen := maxLen
 
 	// After the header (bytes 0-3) follows before the data:
@@ -795,7 +843,7 @@ func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
 	// 2 bytes paramID
 	const dataOffset = 1 + 4 + 2
 
-	// Can not use the write buffer since
+	// Cannot use the write buffer since
 	// a) the buffer is too small
 	// b) it is in use
 	data := make([]byte, 4+1+4+2+len(arg))
@@ -850,6 +898,12 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 	const minPktLen = 4 + 1 + 4 + 1 + 4
 	mc := stmt.mc
 
+	// Determine threshould dynamically to avoid packet size shortage.
+	longDataSize := mc.maxAllowedPacket / (stmt.paramCount + 1)
+	if longDataSize < 64 {
+		longDataSize = 64
+	}
+
 	// Reset packet-sequence
 	mc.sequence = 0
 
@@ -861,9 +915,9 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
 		data = mc.buf.takeCompleteBuffer()
 	}
 	if data == nil {
-		// can not take the buffer. Something must be wrong with the connection
+		// cannot take the buffer. Something must be wrong with the connection
 		errLog.Print(ErrBusyBuffer)
-		return driver.ErrBadConn
+		return errBadConnNoWrite
 	}
 
 	// command [1 byte]
@@ -922,7 +976,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
 			}
@@ -930,7 +984,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 {
@@ -946,7 +1000,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 {
@@ -962,7 +1016,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 {
@@ -974,10 +1028,10 @@ 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.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
+					if len(v) < longDataSize {
 						paramValues = appendLengthEncodedInteger(paramValues,
 							uint64(len(v)),
 						)
@@ -992,14 +1046,14 @@ 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.maxPacketAllowed-pos-len(paramValues)-(len(args)-(i+1))*64 {
+				if len(v) < longDataSize {
 					paramValues = appendLengthEncodedInteger(paramValues,
 						uint64(len(v)),
 					)
@@ -1011,23 +1065,25 @@ 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)
+				return fmt.Errorf("cannot convert type: %T", arg)
 			}
 		}
 
@@ -1060,8 +1116,6 @@ func (mc *mysqlConn) discardResults() error {
 			if err := mc.readUntilEOF(); err != nil {
 				return err
 			}
-		} else {
-			mc.status &^= statusMoreResultsExists
 		}
 	}
 	return nil
@@ -1079,16 +1133,17 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 		// EOF Packet
 		if data[0] == iEOF && len(data) == 5 {
 			rows.mc.status = readStatus(data[3:])
-			if err := rows.mc.discardResults(); err != nil {
-				return err
+			rows.rs.done = true
+			if !rows.HasNextResultSet() {
+				rows.mc = nil
 			}
-			rows.mc = nil
 			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]
@@ -1104,14 +1159,14 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 		}
 
 		// Convert to byte-coded string
-		switch rows.columns[i].fieldType {
+		switch rows.rs.columns[i].fieldType {
 		case fieldTypeNULL:
 			dest[i] = nil
 			continue
 
 		// Numeric Types
 		case fieldTypeTiny:
-			if rows.columns[i].flags&flagUnsigned != 0 {
+			if rows.rs.columns[i].flags&flagUnsigned != 0 {
 				dest[i] = int64(data[pos])
 			} else {
 				dest[i] = int64(int8(data[pos]))
@@ -1120,7 +1175,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			continue
 
 		case fieldTypeShort, fieldTypeYear:
-			if rows.columns[i].flags&flagUnsigned != 0 {
+			if rows.rs.columns[i].flags&flagUnsigned != 0 {
 				dest[i] = int64(binary.LittleEndian.Uint16(data[pos : pos+2]))
 			} else {
 				dest[i] = int64(int16(binary.LittleEndian.Uint16(data[pos : pos+2])))
@@ -1129,7 +1184,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			continue
 
 		case fieldTypeInt24, fieldTypeLong:
-			if rows.columns[i].flags&flagUnsigned != 0 {
+			if rows.rs.columns[i].flags&flagUnsigned != 0 {
 				dest[i] = int64(binary.LittleEndian.Uint32(data[pos : pos+4]))
 			} else {
 				dest[i] = int64(int32(binary.LittleEndian.Uint32(data[pos : pos+4])))
@@ -1138,7 +1193,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			continue
 
 		case fieldTypeLongLong:
-			if rows.columns[i].flags&flagUnsigned != 0 {
+			if rows.rs.columns[i].flags&flagUnsigned != 0 {
 				val := binary.LittleEndian.Uint64(data[pos : pos+8])
 				if val > math.MaxInt64 {
 					dest[i] = uint64ToString(val)
@@ -1152,7 +1207,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
 
@@ -1192,10 +1247,10 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 			case isNull:
 				dest[i] = nil
 				continue
-			case rows.columns[i].fieldType == fieldTypeTime:
+			case rows.rs.columns[i].fieldType == fieldTypeTime:
 				// database/sql does not support an equivalent to TIME, return a string
 				var dstlen uint8
-				switch decimals := rows.columns[i].decimals; decimals {
+				switch decimals := rows.rs.columns[i].decimals; decimals {
 				case 0x00, 0x1f:
 					dstlen = 8
 				case 1, 2, 3, 4, 5, 6:
@@ -1203,18 +1258,18 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 				default:
 					return fmt.Errorf(
 						"protocol error, illegal decimals value %d",
-						rows.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:
 				dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
 			default:
 				var dstlen uint8
-				if rows.columns[i].fieldType == fieldTypeDate {
+				if rows.rs.columns[i].fieldType == fieldTypeDate {
 					dstlen = 10
 				} else {
-					switch decimals := rows.columns[i].decimals; decimals {
+					switch decimals := rows.rs.columns[i].decimals; decimals {
 					case 0x00, 0x1f:
 						dstlen = 19
 					case 1, 2, 3, 4, 5, 6:
@@ -1222,11 +1277,11 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 					default:
 						return fmt.Errorf(
 							"protocol error, illegal decimals value %d",
-							rows.columns[i].decimals,
+							rows.rs.columns[i].decimals,
 						)
 					}
 				}
-				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, false)
+				dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen)
 			}
 
 			if err == nil {
@@ -1238,7 +1293,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
 
 		// Please report if this happens!
 		default:
-			return fmt.Errorf("unknown field type %d", rows.columns[i].fieldType)
+			return fmt.Errorf("unknown field type %d", rows.rs.columns[i].fieldType)
 		}
 	}
 

+ 139 - 35
vendor/github.com/go-sql-driver/mysql/rows.go

@@ -11,19 +11,20 @@ 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
+	columnNames []string
+	done        bool
 }
 
 type mysqlRows struct {
-	mc      *mysqlConn
-	columns []mysqlField
+	mc     *mysqlConn
+	rs     resultSet
+	finish func()
 }
 
 type binaryRows struct {
@@ -34,37 +35,86 @@ type textRows struct {
 	mysqlRows
 }
 
-type emptyRows struct{}
-
 func (rows *mysqlRows) Columns() []string {
-	columns := make([]string, len(rows.columns))
+	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 {
-			if tableName := rows.columns[i].tableName; len(tableName) > 0 {
-				columns[i] = tableName + "." + rows.columns[i].name
+			if tableName := rows.rs.columns[i].tableName; len(tableName) > 0 {
+				columns[i] = tableName + "." + rows.rs.columns[i].name
 			} else {
-				columns[i] = rows.columns[i].name
+				columns[i] = rows.rs.columns[i].name
 			}
 		}
 	} else {
 		for i := range columns {
-			columns[i] = rows.columns[i].name
+			columns[i] = rows.rs.columns[i].name
 		}
 	}
+
+	rows.rs.columnNames = columns
 	return columns
 }
 
-func (rows *mysqlRows) Close() error {
+func (rows *mysqlRows) ColumnTypeDatabaseTypeName(i int) string {
+	return rows.rs.columns[i].typeDatabaseName()
+}
+
+// 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
-	err := mc.readUntilEOF()
+	if !rows.rs.done {
+		err = mc.readUntilEOF()
+	}
 	if err == nil {
 		if err = mc.discardResults(); err != nil {
 			return err
@@ -75,22 +125,66 @@ func (rows *mysqlRows) Close() error {
 	return err
 }
 
-func (rows *binaryRows) Next(dest []driver.Value) error {
-	if mc := rows.mc; mc != nil {
-		if mc.netConn == nil {
-			return ErrInvalidConn
+func (rows *mysqlRows) HasNextResultSet() (b bool) {
+	if rows.mc == nil {
+		return false
+	}
+	return rows.mc.status&statusMoreResultsExists != 0
+}
+
+func (rows *mysqlRows) nextResultSet() (int, error) {
+	if rows.mc == nil {
+		return 0, io.EOF
+	}
+	if err := rows.mc.error(); err != nil {
+		return 0, err
+	}
+
+	// Remove unread packets from stream
+	if !rows.rs.done {
+		if err := rows.mc.readUntilEOF(); err != nil {
+			return 0, err
 		}
+		rows.rs.done = true
+	}
 
-		// Fetch next row from stream
-		return rows.readRow(dest)
+	if !rows.HasNextResultSet() {
+		rows.mc = nil
+		return 0, io.EOF
 	}
-	return io.EOF
+	rows.rs = resultSet{}
+	return rows.mc.readResultSetHeaderPacket()
 }
 
-func (rows *textRows) Next(dest []driver.Value) error {
+func (rows *mysqlRows) nextNotEmptyResultSet() (int, error) {
+	for {
+		resLen, err := rows.nextResultSet()
+		if err != nil {
+			return 0, err
+		}
+
+		if resLen > 0 {
+			return resLen, nil
+		}
+
+		rows.rs.done = true
+	}
+}
+
+func (rows *binaryRows) NextResultSet() error {
+	resLen, err := rows.nextNotEmptyResultSet()
+	if err != nil {
+		return err
+	}
+
+	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
@@ -99,14 +193,24 @@ func (rows *textRows) Next(dest []driver.Value) error {
 	return io.EOF
 }
 
-func (rows emptyRows) Columns() []string {
-	return nil
-}
+func (rows *textRows) NextResultSet() (err error) {
+	resLen, err := rows.nextNotEmptyResultSet()
+	if err != nil {
+		return err
+	}
 
-func (rows emptyRows) Close() error {
-	return nil
+	rows.rs.columns, err = rows.mc.readColumns(resLen)
+	return err
 }
 
-func (rows emptyRows) Next(dest []driver.Value) error {
+func (rows *textRows) Next(dest []driver.Value) error {
+	if mc := rows.mc; mc != nil {
+		if err := mc.error(); err != nil {
+			return err
+		}
+
+		// Fetch next row from stream
+		return rows.readRow(dest)
+	}
 	return io.EOF
 }

+ 93 - 32
vendor/github.com/go-sql-driver/mysql/statement.go

@@ -11,6 +11,7 @@ package mysql
 import (
 	"database/sql/driver"
 	"fmt"
+	"io"
 	"reflect"
 	"strconv"
 )
@@ -19,12 +20,14 @@ 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 {
-		errLog.Print(ErrInvalidConn)
+	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.
+		//errLog.Print(ErrInvalidConn)
 		return driver.ErrBadConn
 	}
 
@@ -42,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
@@ -59,37 +62,45 @@ func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
 
 	// Read Result
 	resLen, err := mc.readResultSetHeaderPacket()
-	if err == nil {
-		if resLen > 0 {
-			// Columns
-			err = mc.readUntilEOF()
-			if err != nil {
-				return nil, err
-			}
-
-			// Rows
-			err = mc.readUntilEOF()
+	if err != nil {
+		return nil, err
+	}
+
+	if resLen > 0 {
+		// Columns
+		if err = mc.readUntilEOF(); err != nil {
+			return nil, err
 		}
-		if err == nil {
-			return &mysqlResult{
-				affectedRows: int64(mc.affectedRows),
-				insertId:     int64(mc.insertId),
-			}, nil
+
+		// Rows
+		if err := mc.readUntilEOF(); err != nil {
+			return nil, err
 		}
 	}
 
-	return nil, err
+	if err := mc.discardResults(); err != nil {
+		return nil, err
+	}
+
+	return &mysqlResult{
+		affectedRows: int64(mc.affectedRows),
+		insertId:     int64(mc.insertId),
+	}, nil
 }
 
 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
@@ -104,14 +115,15 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
 
 	if resLen > 0 {
 		rows.mc = mc
-		// Columns
-		// If not cached, read them and cache them
-		if stmt.columns == nil {
-			rows.columns, err = mc.readColumns(resLen)
-			stmt.columns = rows.columns
-		} else {
-			rows.columns = stmt.columns
-			err = mc.readUntilEOF()
+		rows.rs.columns, err = mc.readColumns(resLen)
+	} else {
+		rows.rs.done = true
+
+		switch err := rows.NextResultSet(); err {
+		case nil, io.EOF:
+			return rows, nil
+		default:
+			return nil, err
 		}
 	}
 
@@ -120,19 +132,36 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
 
 type converter struct{}
 
+// ConvertValue mirrors the reference/default converter in database/sql/driver
+// with _one_ exception.  We support uint64 with their high bit and the default
+// implementation does not.  This function should be kept in sync with
+// database/sql/driver defaultConverter.ConvertValue() except for that
+// deliberate difference.
 func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
 	if driver.IsValue(v) {
 		return v, nil
 	}
 
+	if vr, ok := v.(driver.Valuer); ok {
+		sv, err := callValuerValue(vr)
+		if err != nil {
+			return nil, err
+		}
+		if !driver.IsValue(sv) {
+			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
+		}
+		return sv, nil
+	}
+
 	rv := reflect.ValueOf(v)
 	switch rv.Kind() {
 	case reflect.Ptr:
 		// indirect pointers
 		if rv.IsNil() {
 			return nil, nil
+		} else {
+			return c.ConvertValue(rv.Elem().Interface())
 		}
-		return c.ConvertValue(rv.Elem().Interface())
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 		return rv.Int(), nil
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
@@ -145,6 +174,38 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
 		return int64(u64), nil
 	case reflect.Float32, reflect.Float64:
 		return rv.Float(), nil
+	case reflect.Bool:
+		return rv.Bool(), nil
+	case reflect.Slice:
+		ek := rv.Type().Elem().Kind()
+		if ek == reflect.Uint8 {
+			return rv.Bytes(), nil
+		}
+		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
+	case reflect.String:
+		return rv.String(), nil
 	}
 	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
 }
+
+var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+
+// callValuerValue returns vr.Value(), with one exception:
+// If vr.Value is an auto-generated method on a pointer type and the
+// pointer is nil, it would panic at runtime in the panicwrap
+// method. Treat it like nil instead.
+//
+// This is so people can implement driver.Value on value types and
+// still use nil pointers to those types to mean nil/NULL, just like
+// string/*string.
+//
+// This is an exact copy of the same-named unexported function from the
+// database/sql package.
+func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
+	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
+		rv.IsNil() &&
+		rv.Type().Elem().Implements(valuerReflectType) {
+		return nil, nil
+	}
+	return vr.Value()
+}

+ 2 - 2
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")

+ 210 - 224
vendor/github.com/go-sql-driver/mysql/utils.go

@@ -9,23 +9,30 @@
 package mysql
 
 import (
-	"crypto/sha1"
 	"crypto/tls"
 	"database/sql/driver"
 	"encoding/binary"
 	"fmt"
 	"io"
+	"strconv"
 	"strings"
+	"sync"
+	"sync/atomic"
 	"time"
 )
 
+// Registry for custom tls.Configs
 var (
-	tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs
+	tlsConfigLock     sync.RWMutex
+	tlsConfigRegistry map[string]*tls.Config
 )
 
 // 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 provided tls.Config is exclusively owned by the driver after
+// registering it.
+//
 //  rootCertPool := x509.NewCertPool()
 //  pem, err := ioutil.ReadFile("/path/ca-cert.pem")
 //  if err != nil {
@@ -51,19 +58,32 @@ func RegisterTLSConfig(key string, config *tls.Config) error {
 		return fmt.Errorf("key '%s' is reserved", key)
 	}
 
-	if tlsConfigRegister == nil {
-		tlsConfigRegister = make(map[string]*tls.Config)
+	tlsConfigLock.Lock()
+	if tlsConfigRegistry == nil {
+		tlsConfigRegistry = make(map[string]*tls.Config)
 	}
 
-	tlsConfigRegister[key] = config
+	tlsConfigRegistry[key] = config
+	tlsConfigLock.Unlock()
 	return nil
 }
 
 // DeregisterTLSConfig removes the tls.Config associated with key.
 func DeregisterTLSConfig(key string) {
-	if tlsConfigRegister != nil {
-		delete(tlsConfigRegister, key)
+	tlsConfigLock.Lock()
+	if tlsConfigRegistry != nil {
+		delete(tlsConfigRegistry, key)
 	}
+	tlsConfigLock.Unlock()
+}
+
+func getTLSConfigClone(key string) (config *tls.Config) {
+	tlsConfigLock.RLock()
+	if v, ok := tlsConfigRegistry[key]; ok {
+		config = cloneTLSConfig(v)
+	}
+	tlsConfigLock.RUnlock()
+	return
 }
 
 // Returns the bool value of the input.
@@ -80,119 +100,6 @@ func readBool(input string) (value bool, valid bool) {
 	return
 }
 
-/******************************************************************************
-*                             Authentication                                  *
-******************************************************************************/
-
-// Encrypt password using 4.1+ method
-func scramblePassword(scramble, password []byte) []byte {
-	if len(password) == 0 {
-		return nil
-	}
-
-	// stage1Hash = SHA1(password)
-	crypt := sha1.New()
-	crypt.Write(password)
-	stage1 := crypt.Sum(nil)
-
-	// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
-	// inner Hash
-	crypt.Reset()
-	crypt.Write(stage1)
-	hash := crypt.Sum(nil)
-
-	// outer Hash
-	crypt.Reset()
-	crypt.Write(scramble)
-	crypt.Write(hash)
-	scramble = crypt.Sum(nil)
-
-	// token = scrambleHash XOR stage1Hash
-	for i := range scramble {
-		scramble[i] ^= stage1[i]
-	}
-	return scramble
-}
-
-// Encrypt password using pre 4.1 (old password) method
-// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
-type myRnd struct {
-	seed1, seed2 uint32
-}
-
-const myRndMaxVal = 0x3FFFFFFF
-
-// Pseudo random number generator
-func newMyRnd(seed1, seed2 uint32) *myRnd {
-	return &myRnd{
-		seed1: seed1 % myRndMaxVal,
-		seed2: seed2 % myRndMaxVal,
-	}
-}
-
-// Tested to be equivalent to MariaDB's floating point variant
-// http://play.golang.org/p/QHvhd4qved
-// http://play.golang.org/p/RG0q4ElWDx
-func (r *myRnd) NextByte() byte {
-	r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
-	r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
-
-	return byte(uint64(r.seed1) * 31 / myRndMaxVal)
-}
-
-// Generate binary hash from byte string using insecure pre 4.1 method
-func pwHash(password []byte) (result [2]uint32) {
-	var add uint32 = 7
-	var tmp uint32
-
-	result[0] = 1345345333
-	result[1] = 0x12345671
-
-	for _, c := range password {
-		// skip spaces and tabs in password
-		if c == ' ' || c == '\t' {
-			continue
-		}
-
-		tmp = uint32(c)
-		result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
-		result[1] += (result[1] << 8) ^ result[0]
-		add += tmp
-	}
-
-	// Remove sign bit (1<<31)-1)
-	result[0] &= 0x7FFFFFFF
-	result[1] &= 0x7FFFFFFF
-
-	return
-}
-
-// Encrypt password using insecure pre 4.1 method
-func scrambleOldPassword(scramble, password []byte) []byte {
-	if len(password) == 0 {
-		return nil
-	}
-
-	scramble = scramble[:8]
-
-	hashPw := pwHash(password)
-	hashSc := pwHash(scramble)
-
-	r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
-
-	var out [8]byte
-	for i := range out {
-		out[i] = r.NextByte() + 64
-	}
-
-	mask := r.NextByte()
-	for i := range out {
-		out[i] ^= mask
-	}
-
-	return out[:]
-}
-
 /******************************************************************************
 *                           Time related utils                                *
 ******************************************************************************/
@@ -321,139 +228,154 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
 const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
 const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
 
-func formatBinaryDateTime(src []byte, length uint8, justTime bool) (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 justTime {
-			return zeroDateTime[11 : 11+length], nil
-		}
-		return zeroDateTime[:length], nil
-	}
-	var dst []byte          // return value
-	var pt, p1, p2, p3 byte // current digit pair
-	var zOffs byte          // offset of value in zeroDateTime
-	if justTime {
-		switch length {
-		case
-			8,                      // time (can be up to 10 when negative and 100+ hours)
-			10, 11, 12, 13, 14, 15: // time with fractional seconds
-		default:
-			return nil, fmt.Errorf("illegal TIME length %d", length)
-		}
-		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, '-')
-		}
-		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:]
-	}
-	// p1 is 2-digit hour, src is after hour
-	p2, p3 = src[0], src[1]
-	dst = append(dst,
-		digits10[p1], digits01[p1], ':',
-		digits10[p2], digits01[p2], ':',
-		digits10[p3], digits01[p3],
-	)
-	if length <= byte(len(dst)) {
-		return dst, nil
+func appendMicrosecs(dst, src []byte, decimals int) []byte {
+	if decimals <= 0 {
+		return dst
 	}
-	src = src[2:]
 	if len(src) == 0 {
-		return append(dst, zeroDateTime[19:zOffs+length]...), nil
+		return append(dst, ".000000"[:decimals+1]...)
 	}
+
 	microsecs := binary.LittleEndian.Uint32(src[:4])
-	p1 = byte(microsecs / 10000)
+	p1 := byte(microsecs / 10000)
 	microsecs -= 10000 * uint32(p1)
-	p2 = byte(microsecs / 100)
+	p2 := byte(microsecs / 100)
 	microsecs -= 100 * uint32(p2)
-	p3 = byte(microsecs)
-	switch decimals := zOffs + length - 20; decimals {
+	p3 := byte(microsecs)
+
+	switch decimals {
 	default:
 		return append(dst, '.',
 			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
+		)
+	}
+}
+
+func formatBinaryDateTime(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 {
+		return zeroDateTime[:length], nil
+	}
+	var dst []byte      // return value
+	var p1, p2, p3 byte // current digit pair
+
+	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 := 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
+	p2, p3 = src[0], src[1]
+	dst = append(dst,
+		digits10[p1], digits01[p1], ':',
+		digits10[p2], digits01[p2], ':',
+		digits10[p3], digits01[p3],
+	)
+	return appendMicrosecs(dst, src[2:], int(length)-20), nil
+}
+
+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 {
+		return zeroDateTime[11 : 11+length], nil
+	}
+	var dst []byte // return value
+
+	switch length {
+	case
+		8,                      // time (can be up to 10 when negative and 100+ hours)
+		10, 11, 12, 13, 14, 15: // time with fractional seconds
+	default:
+		return nil, fmt.Errorf("illegal TIME length %d", length)
+	}
+	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
 }
 
 /******************************************************************************
@@ -519,7 +441,7 @@ func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {
 
 	// Check data length
 	if len(b) >= n {
-		return b[n-int(num) : n], false, n, nil
+		return b[n-int(num) : n : n], false, n, nil
 	}
 	return nil, false, n, io.EOF
 }
@@ -548,8 +470,8 @@ func readLengthEncodedInteger(b []byte) (uint64, bool, int) {
 	if len(b) == 0 {
 		return 0, true, 1
 	}
-	switch b[0] {
 
+	switch b[0] {
 	// 251: NULL
 	case 0xfb:
 		return 0, true, 1
@@ -738,3 +660,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
+}
+
+// atomicError 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
+}

+ 40 - 0
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,
+	}
+}

+ 50 - 0
vendor/github.com/go-sql-driver/mysql/utils_go18.go

@@ -0,0 +1,50 @@
+// 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)
+	}
+}

+ 3 - 3
vendor/vendor.json

@@ -147,10 +147,10 @@
 			"revisionTime": "2017-02-20T18:37:56Z"
 		},
 		{
-			"checksumSHA1": "jEXpLrWXoQvH/zk1lW5Si0swr6Y=",
+			"checksumSHA1": "uLlP+3wneMxXVKTGi9zZZVnpZlI=",
 			"path": "github.com/go-sql-driver/mysql",
-			"revision": "0b58b37b664c21f3010e836f1b931e1d0b0b0685",
-			"revisionTime": "2016-08-02T11:38:42Z"
+			"revision": "2307b45d3a41dcc64a2bf46db80f61fd182e0186",
+			"revisionTime": "2018-06-12T15:06:50Z"
 		},
 		{
 			"checksumSHA1": "MjpLNawWs5TXcO1vjaZo8PjnYM4=",