From 42f28ab8e374137fe3f5d25424489d879d4724f8 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Wed, 21 Jun 2017 19:06:17 -0700 Subject: Updating server dependancies (#6712) --- vendor/github.com/go-sql-driver/mysql/.travis.yml | 79 --------- .../go-sql-driver/mysql/.travis/docker.cnf | 5 - .../go-sql-driver/mysql/.travis/wait_mysql.sh | 8 - vendor/github.com/go-sql-driver/mysql/AUTHORS | 6 - vendor/github.com/go-sql-driver/mysql/README.md | 48 +++--- .../github.com/go-sql-driver/mysql/connection.go | 36 ++-- vendor/github.com/go-sql-driver/mysql/driver.go | 2 +- .../go-sql-driver/mysql/driver_go18_test.go | 190 --------------------- .../github.com/go-sql-driver/mysql/driver_test.go | 67 ++------ vendor/github.com/go-sql-driver/mysql/dsn.go | 4 - vendor/github.com/go-sql-driver/mysql/infile.go | 3 +- vendor/github.com/go-sql-driver/mysql/packets.go | 77 +++++---- .../github.com/go-sql-driver/mysql/packets_test.go | 8 +- vendor/github.com/go-sql-driver/mysql/rows.go | 112 +++--------- vendor/github.com/go-sql-driver/mysql/statement.go | 55 +++--- 15 files changed, 138 insertions(+), 562 deletions(-) delete mode 100644 vendor/github.com/go-sql-driver/mysql/.travis/docker.cnf delete mode 100755 vendor/github.com/go-sql-driver/mysql/.travis/wait_mysql.sh delete mode 100644 vendor/github.com/go-sql-driver/mysql/driver_go18_test.go (limited to 'vendor/github.com/go-sql-driver/mysql') diff --git a/vendor/github.com/go-sql-driver/mysql/.travis.yml b/vendor/github.com/go-sql-driver/mysql/.travis.yml index a551785b8..c1cc10aaf 100644 --- a/vendor/github.com/go-sql-driver/mysql/.travis.yml +++ b/vendor/github.com/go-sql-driver/mysql/.travis.yml @@ -7,86 +7,7 @@ go: - 1.5 - 1.6 - 1.7 - - 1.8 - tip -before_install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - -matrix: - include: - - env: DB=MYSQL57 - sudo: required - dist: trusty - go: 1.8 - services: - - docker - before_install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - - docker pull mysql:5.7 - - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - mysql:5.7 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB - - sleep 30 - - cp .travis/docker.cnf ~/.my.cnf - - mysql --print-defaults - - .travis/wait_mysql.sh - before_script: - - export MYSQL_TEST_USER=gotest - - export MYSQL_TEST_PASS=secret - - export MYSQL_TEST_ADDR=127.0.0.1:3307 - - export MYSQL_TEST_CONCURRENT=1 - - - env: DB=MARIA55 - sudo: required - dist: trusty - go: 1.8 - services: - - docker - before_install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - - docker pull mariadb:5.5 - - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - mariadb:5.5 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB - - sleep 30 - - cp .travis/docker.cnf ~/.my.cnf - - mysql --print-defaults - - .travis/wait_mysql.sh - before_script: - - export MYSQL_TEST_USER=gotest - - export MYSQL_TEST_PASS=secret - - export MYSQL_TEST_ADDR=127.0.0.1:3307 - - export MYSQL_TEST_CONCURRENT=1 - - - env: DB=MARIA10_1 - sudo: required - dist: trusty - go: 1.8 - services: - - docker - before_install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls - - docker pull mariadb:10.1 - - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - mariadb:10.1 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB - - sleep 30 - - cp .travis/docker.cnf ~/.my.cnf - - mysql --print-defaults - - .travis/wait_mysql.sh - before_script: - - export MYSQL_TEST_USER=gotest - - export MYSQL_TEST_PASS=secret - - export MYSQL_TEST_ADDR=127.0.0.1:3307 - - export MYSQL_TEST_CONCURRENT=1 - - before_script: - mysql -e 'create database gotest;' -script: - - go test -v -covermode=count -coverprofile=coverage.out - - go vet ./... - - test -z "$(gofmt -d -s . | tee /dev/stderr)" - - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/vendor/github.com/go-sql-driver/mysql/.travis/docker.cnf b/vendor/github.com/go-sql-driver/mysql/.travis/docker.cnf deleted file mode 100644 index e57754e5a..000000000 --- a/vendor/github.com/go-sql-driver/mysql/.travis/docker.cnf +++ /dev/null @@ -1,5 +0,0 @@ -[client] -user = gotest -password = secret -host = 127.0.0.1 -port = 3307 diff --git a/vendor/github.com/go-sql-driver/mysql/.travis/wait_mysql.sh b/vendor/github.com/go-sql-driver/mysql/.travis/wait_mysql.sh deleted file mode 100755 index abcf5f0ae..000000000 --- a/vendor/github.com/go-sql-driver/mysql/.travis/wait_mysql.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -while : -do - sleep 3 - if mysql -e 'select version()'; then - break - fi -done diff --git a/vendor/github.com/go-sql-driver/mysql/AUTHORS b/vendor/github.com/go-sql-driver/mysql/AUTHORS index 1928dac89..692c186fd 100644 --- a/vendor/github.com/go-sql-driver/mysql/AUTHORS +++ b/vendor/github.com/go-sql-driver/mysql/AUTHORS @@ -13,31 +13,26 @@ Aaron Hopkins Arne Hormann -Asta Xie Carlos Nieto Chris Moos Daniel Nichter Daniël van Eeden DisposaBoy -Egor Smolyakov Frederick Mayle Gustavo Kristic Hanno Braun Henri Yandell Hirotaka Yamamoto INADA Naoki -Jacek Szwec James Harr Jian Zhen Joshua Prunier Julien Lefevre Julien Schmidt -Justin Nuß Kamil Dziedzic Kevin Malachowski Lennart Rudolph Leonardo YongUk Kim -Lion Yang Luca Looz Lucas Liu Luke Scott @@ -45,7 +40,6 @@ Michael Woolnough Nicola Peduzzi Olivier Mengué Paul Bonser -Peter Schultz Runrioter Wung Soroush Pour Stan Putrya diff --git a/vendor/github.com/go-sql-driver/mysql/README.md b/vendor/github.com/go-sql-driver/mysql/README.md index a060e3cfd..a16012f81 100644 --- a/vendor/github.com/go-sql-driver/mysql/README.md +++ b/vendor/github.com/go-sql-driver/mysql/README.md @@ -1,6 +1,6 @@ # Go-MySQL-Driver -A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) package +A MySQL-Driver for Go's [database/sql](http://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") @@ -15,7 +15,6 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac * [Address](#address) * [Parameters](#parameters) * [Examples](#examples) - * [Connection pool and timeouts](#connection-pool-and-timeouts) * [LOAD DATA LOCAL INFILE support](#load-data-local-infile-support) * [time.Time support](#timetime-support) * [Unicode support](#unicode-support) @@ -27,11 +26,11 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac ## 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](https://godoc.org/github.com/go-sql-driver/mysql#DialFunc) + * Connections over TCP/IPv4, TCP/IPv6, Unix domain sockets or [custom protocols](http://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`](https://golang.org/pkg/database/sql/#RawBytes) support. + * Full [`sql.RawBytes`](http://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 @@ -44,14 +43,14 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac --------------------------------------- ## Installation -Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell: +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: ```bash $ go get github.com/go-sql-driver/mysql ``` -Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`. +Make sure [Git is installed](http://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`](https://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`](http://golang.org/pkg/database/sql) API then. Use `mysql` as `driverName` and a valid [DSN](#dsn-data-source-name) as `dataSourceName`: ```go @@ -96,13 +95,13 @@ 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](https://golang.org/pkg/net/#Dial) for more information which networks are available. +See [net.Dial](http://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`. If `host` is a literal IPv6 address, it must be enclosed in square brackets. -The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form. +The functions [net.JoinHostPort](http://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](http://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`. @@ -221,11 +220,11 @@ Valid Values: Default: UTC ``` -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. +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. 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](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`. +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`. ##### `maxAllowedPacket` ``` @@ -261,11 +260,11 @@ Default: false ##### `readTimeout` ``` -Type: duration +Type: decimal number Default: 0 ``` -I/O read timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. +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"*. ##### `strict` @@ -284,11 +283,11 @@ By default MySQL also treats notes as warnings. Use [`sql_notes=false`](http://d ##### `timeout` ``` -Type: duration +Type: decimal number Default: OS default ``` -Timeout for establishing connections, aka dial timeout. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*. +*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). ##### `tls` @@ -298,16 +297,16 @@ Valid Values: true, false, skip-verify, Default: false ``` -`tls=true` enables TLS / SSL encrypted connection to the server. Use `skip-verify` if you want to use a self-signed or invalid certificate (server side). Use a custom value registered with [`mysql.RegisterTLSConfig`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterTLSConfig). +`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). ##### `writeTimeout` ``` -Type: duration +Type: decimal number Default: 0 ``` -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"*. +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"*. ##### System Variables @@ -381,11 +380,6 @@ 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. - - ### `LOAD DATA LOCAL INFILE` support For this feature you need direct access to the package. Therefore you must change the import path (no `_`): ```go @@ -396,17 +390,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::` then. Choose different names for different handlers and `DeregisterReaderHandler` when you don't need it anymore. -See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/mysql "golang mysql driver documentation") for details. +See the [godoc of Go-MySQL-Driver](http://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. -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. +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. **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`](https://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`](http://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 @@ -441,7 +435,7 @@ That means: * When distributing, you **must publish** the source code of any **changed files** licensed under the MPL 2.0 under a) the MPL 2.0 itself or b) a compatible license (e.g. GPL 3.0 or Apache License 2.0) * You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged** -Please read the [MPL 2.0 FAQ](https://www.mozilla.org/en-US/MPL/2.0/FAQ/) if you have further questions regarding the license. +Please read the [MPL 2.0 FAQ](http://www.mozilla.org/MPL/2.0/FAQ.html) 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) diff --git a/vendor/github.com/go-sql-driver/mysql/connection.go b/vendor/github.com/go-sql-driver/mysql/connection.go index cdce3e30f..d82c728f3 100644 --- a/vendor/github.com/go-sql-driver/mysql/connection.go +++ b/vendor/github.com/go-sql-driver/mysql/connection.go @@ -10,7 +10,6 @@ package mysql import ( "database/sql/driver" - "io" "net" "strconv" "strings" @@ -272,6 +271,7 @@ 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 @@ -289,29 +289,22 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err // Internal function to execute commands func (mc *mysqlConn) exec(query string) error { // Send command - if err := mc.writeCommandPacketStr(comQuery, query); err != nil { + err := mc.writeCommandPacketStr(comQuery, query) + if err != nil { return err } // Read Result resLen, err := mc.readResultSetHeaderPacket() - if err != nil { - return err - } - - if resLen > 0 { - // columns - if err := mc.readUntilEOF(); err != nil { + if err == nil && resLen > 0 { + if err = mc.readUntilEOF(); err != nil { return err } - // rows - if err := mc.readUntilEOF(); err != nil { - return err - } + err = mc.readUntilEOF() } - return mc.discardResults() + return err } func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) { @@ -329,6 +322,7 @@ 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) @@ -341,17 +335,11 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro rows.mc = mc if resLen == 0 { - rows.rs.done = true - - switch err := rows.NextResultSet(); err { - case nil, io.EOF: - return rows, nil - default: - return nil, err - } + // no columns, no more data + return emptyRows{}, nil } // Columns - rows.rs.columns, err = mc.readColumns(resLen) + rows.columns, err = mc.readColumns(resLen) return rows, err } } @@ -371,7 +359,7 @@ func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) { if err == nil { rows := new(textRows) rows.mc = mc - rows.rs.columns = []mysqlField{{fieldType: fieldTypeVarChar}} + rows.columns = []mysqlField{{fieldType: fieldTypeVarChar}} if resLen > 0 { // Columns diff --git a/vendor/github.com/go-sql-driver/mysql/driver.go b/vendor/github.com/go-sql-driver/mysql/driver.go index e51d98a3c..0022d1f1e 100644 --- a/vendor/github.com/go-sql-driver/mysql/driver.go +++ b/vendor/github.com/go-sql-driver/mysql/driver.go @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at http://mozilla.org/MPL/2.0/. -// Package mysql provides a MySQL driver for Go's database/sql package. +// Package mysql provides a MySQL driver for Go's database/sql package // // The driver should be used via the database/sql package: // diff --git a/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go b/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go deleted file mode 100644 index 93918ad46..000000000 --- a/vendor/github.com/go-sql-driver/mysql/driver_go18_test.go +++ /dev/null @@ -1,190 +0,0 @@ -// +build go1.8 - -package mysql - -import ( - "database/sql" - "fmt" - "reflect" - "testing" -) - -func TestMultiResultSet(t *testing.T) { - type result struct { - values [][]int - columns []string - } - - // checkRows is a helper test function to validate rows containing 3 result - // sets with specific values and columns. The basic query would look like this: - // - // SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - // SELECT 0 UNION SELECT 1; - // SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - // - // to distinguish test cases the first string argument is put in front of - // every error or fatal message. - checkRows := func(desc string, rows *sql.Rows, dbt *DBTest) { - expected := []result{ - { - values: [][]int{{1, 2}, {3, 4}}, - columns: []string{"col1", "col2"}, - }, - { - values: [][]int{{1, 2, 3}, {4, 5, 6}}, - columns: []string{"col1", "col2", "col3"}, - }, - } - - var res1 result - for rows.Next() { - var res [2]int - if err := rows.Scan(&res[0], &res[1]); err != nil { - dbt.Fatal(err) - } - res1.values = append(res1.values, res[:]) - } - - cols, err := rows.Columns() - if err != nil { - dbt.Fatal(desc, err) - } - res1.columns = cols - - if !reflect.DeepEqual(expected[0], res1) { - dbt.Error(desc, "want =", expected[0], "got =", res1) - } - - if !rows.NextResultSet() { - dbt.Fatal(desc, "expected next result set") - } - - // ignoring one result set - - if !rows.NextResultSet() { - dbt.Fatal(desc, "expected next result set") - } - - var res2 result - cols, err = rows.Columns() - if err != nil { - dbt.Fatal(desc, err) - } - res2.columns = cols - - for rows.Next() { - var res [3]int - if err := rows.Scan(&res[0], &res[1], &res[2]); err != nil { - dbt.Fatal(desc, err) - } - res2.values = append(res2.values, res[:]) - } - - if !reflect.DeepEqual(expected[1], res2) { - dbt.Error(desc, "want =", expected[1], "got =", res2) - } - - if rows.NextResultSet() { - dbt.Error(desc, "unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error(desc, err) - } - } - - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery(`DO 1; - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - DO 1; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6;`) - defer rows.Close() - checkRows("query: ", rows, dbt) - }) - - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - queries := []string{ - ` - DROP PROCEDURE IF EXISTS test_mrss; - CREATE PROCEDURE test_mrss() - BEGIN - DO 1; - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - DO 1; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - END - `, - ` - DROP PROCEDURE IF EXISTS test_mrss; - CREATE PROCEDURE test_mrss() - BEGIN - SELECT 1 AS col1, 2 AS col2 UNION SELECT 3, 4; - SELECT 0 UNION SELECT 1; - SELECT 1 AS col1, 2 AS col2, 3 AS col3 UNION SELECT 4, 5, 6; - END - `, - } - - defer dbt.mustExec("DROP PROCEDURE IF EXISTS test_mrss") - - for i, query := range queries { - dbt.mustExec(query) - - stmt, err := dbt.db.Prepare("CALL test_mrss()") - if err != nil { - dbt.Fatalf("%v (i=%d)", err, i) - } - defer stmt.Close() - - for j := 0; j < 2; j++ { - rows, err := stmt.Query() - if err != nil { - dbt.Fatalf("%v (i=%d) (j=%d)", err, i, j) - } - checkRows(fmt.Sprintf("prepared stmt query (i=%d) (j=%d): ", i, j), rows, dbt) - } - } - }) -} - -func TestMultiResultSetNoSelect(t *testing.T) { - runTestsWithMultiStatement(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery("DO 1; DO 2;") - defer rows.Close() - - if rows.Next() { - dbt.Error("unexpected row") - } - - if rows.NextResultSet() { - dbt.Error("unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error("expected nil; got ", err) - } - }) -} - -// tests if rows are set in a proper state if some results were ignored before -// calling rows.NextResultSet. -func TestSkipResults(t *testing.T) { - runTests(t, dsn, func(dbt *DBTest) { - rows := dbt.mustQuery("SELECT 1, 2") - defer rows.Close() - - if !rows.Next() { - dbt.Error("expected row") - } - - if rows.NextResultSet() { - dbt.Error("unexpected next result set") - } - - if err := rows.Err(); err != nil { - dbt.Error("expected nil; got ", err) - } - }) -} diff --git a/vendor/github.com/go-sql-driver/mysql/driver_test.go b/vendor/github.com/go-sql-driver/mysql/driver_test.go index 07f7e79b9..78e68f5d0 100644 --- a/vendor/github.com/go-sql-driver/mysql/driver_test.go +++ b/vendor/github.com/go-sql-driver/mysql/driver_test.go @@ -684,7 +684,7 @@ func TestDateTime(t *testing.T) { for _, setup := range setups.tests { allowBinTime := true if setup.s == "" { - // fill time string wherever Go can reliable produce it + // fill time string whereever Go can reliable produce it setup.s = setup.t.Format(setups.tlayout) } else if setup.s[0] == '!' { // skip tests using setup.t as source in queries @@ -856,14 +856,14 @@ func TestNULL(t *testing.T) { dbt.Fatal(err) } if b != nil { - dbt.Error("non-nil []byte which should be nil") + dbt.Error("non-nil []byte wich should be nil") } // Read non-nil if err = nonNullStmt.QueryRow().Scan(&b); err != nil { dbt.Fatal(err) } if b == nil { - dbt.Error("nil []byte which should be non-nil") + dbt.Error("nil []byte wich should be non-nil") } // Insert nil b = nil @@ -1054,36 +1054,22 @@ func TestLoadData(t *testing.T) { dbt.Fatalf("rows count mismatch. Got %d, want 4", i) } } - - dbt.db.Exec("DROP TABLE IF EXISTS test") - dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8") - - // Local File file, err := ioutil.TempFile("", "gotest") defer os.Remove(file.Name()) if err != nil { dbt.Fatal(err) } - RegisterLocalFile(file.Name()) - - // Try first with empty file - dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name())) - var count int - err = dbt.db.QueryRow("SELECT COUNT(*) FROM test").Scan(&count) - if err != nil { - dbt.Fatal(err.Error()) - } - if count != 0 { - dbt.Fatalf("unexpected row count: got %d, want 0", count) - } - - // Then fille File with data and try to load it file.WriteString("1\ta string\n2\ta string containing a \\t\n3\ta string containing a \\n\n4\ta string containing both \\t\\n\n") file.Close() + + dbt.db.Exec("DROP TABLE IF EXISTS test") + dbt.mustExec("CREATE TABLE test (id INT NOT NULL PRIMARY KEY, value TEXT NOT NULL) CHARACTER SET utf8") + + // Local File + RegisterLocalFile(file.Name()) dbt.mustExec(fmt.Sprintf("LOAD DATA LOCAL INFILE %q INTO TABLE test", file.Name())) verifyLoadDataResult() - - // Try with non-existing file + // negative test _, err = dbt.db.Exec("LOAD DATA LOCAL INFILE 'doesnotexist' INTO TABLE test") if err == nil { dbt.Fatal("load non-existent file didn't fail") @@ -1916,36 +1902,3 @@ func TestInterruptBySignal(t *testing.T) { } }) } - -func TestColumnsReusesSlice(t *testing.T) { - rows := mysqlRows{ - rs: resultSet{ - columns: []mysqlField{ - { - tableName: "test", - name: "A", - }, - { - tableName: "test", - name: "B", - }, - }, - }, - } - - allocs := testing.AllocsPerRun(1, func() { - cols := rows.Columns() - - if len(cols) != 2 { - t.Fatalf("expected 2 columns, got %d", len(cols)) - } - }) - - if allocs != 0 { - t.Fatalf("expected 0 allocations, got %d", int(allocs)) - } - - if rows.rs.columnNames == nil { - t.Fatalf("expected columnNames to be set, got nil") - } -} diff --git a/vendor/github.com/go-sql-driver/mysql/dsn.go b/vendor/github.com/go-sql-driver/mysql/dsn.go index 5c828bf90..ac00dcedd 100644 --- a/vendor/github.com/go-sql-driver/mysql/dsn.go +++ b/vendor/github.com/go-sql-driver/mysql/dsn.go @@ -494,10 +494,6 @@ func parseDSNParams(cfg *Config, params string) (err error) { if boolValue { cfg.TLSConfig = "true" cfg.tls = &tls.Config{} - host, _, err := net.SplitHostPort(cfg.Addr) - if err == nil { - cfg.tls.ServerName = host - } } else { cfg.TLSConfig = "false" } diff --git a/vendor/github.com/go-sql-driver/mysql/infile.go b/vendor/github.com/go-sql-driver/mysql/infile.go index 4020f9192..547357cfa 100644 --- a/vendor/github.com/go-sql-driver/mysql/infile.go +++ b/vendor/github.com/go-sql-driver/mysql/infile.go @@ -147,8 +147,7 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) { } // send content packets - // if packetSize == 0, the Reader contains no data - if err == nil && packetSize > 0 { + if err == nil { data := make([]byte, 4+packetSize) var n int for err == nil { diff --git a/vendor/github.com/go-sql-driver/mysql/packets.go b/vendor/github.com/go-sql-driver/mysql/packets.go index cb21397a2..aafe9793e 100644 --- a/vendor/github.com/go-sql-driver/mysql/packets.go +++ b/vendor/github.com/go-sql-driver/mysql/packets.go @@ -486,24 +486,23 @@ func (mc *mysqlConn) readResultOK() ([]byte, error) { plugin := string(data[1:pluginEndIndex]) cipher := data[pluginEndIndex+1 : len(data)-1] - switch plugin { - case "mysql_old_password": + if plugin == "mysql_old_password" { // using old_passwords return cipher, ErrOldPassword - case "mysql_clear_password": + } else if plugin == "mysql_clear_password" { // using clear text password return cipher, ErrCleartextPassword - case "mysql_native_password": + } else if plugin == "mysql_native_password" { // using mysql default authentication method return cipher, ErrNativePassword - default: + } else { return cipher, ErrUnknownPlugin } + } else { + // https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest + return nil, ErrOldPassword } - // https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest - return nil, ErrOldPassword - default: // Error otherwise return nil, mc.handleErrorPacket(data) } @@ -585,8 +584,8 @@ func (mc *mysqlConn) handleOkPacket(data []byte) error { // server_status [2 bytes] mc.status = readStatus(data[1+n+m : 1+n+m+2]) - if mc.status&statusMoreResultsExists != 0 { - return nil + if err := mc.discardResults(); err != nil { + return err } // warning count [2 bytes] @@ -699,10 +698,6 @@ 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 @@ -712,11 +707,15 @@ 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:]) - rows.rs.done = true - if !rows.HasNextResultSet() { - rows.mc = nil + err = rows.mc.discardResults() + if err == nil { + err = io.EOF + } else { + // connection unusable + rows.mc.Close() } - return io.EOF + rows.mc = nil + return err } if data[0] == iERR { rows.mc = nil @@ -737,7 +736,7 @@ func (rows *textRows) readRow(dest []driver.Value) error { if !mc.parseTime { continue } else { - switch rows.rs.columns[i].fieldType { + switch rows.columns[i].fieldType { case fieldTypeTimestamp, fieldTypeDateTime, fieldTypeDate, fieldTypeNewDate: dest[i], err = parseDateTime( @@ -1098,6 +1097,8 @@ func (mc *mysqlConn) discardResults() error { if err := mc.readUntilEOF(); err != nil { return err } + } else { + mc.status &^= statusMoreResultsExists } } return nil @@ -1115,11 +1116,15 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { // EOF Packet if data[0] == iEOF && len(data) == 5 { rows.mc.status = readStatus(data[3:]) - rows.rs.done = true - if !rows.HasNextResultSet() { - rows.mc = nil + err = rows.mc.discardResults() + if err == nil { + err = io.EOF + } else { + // connection unusable + rows.mc.Close() } - return io.EOF + rows.mc = nil + return err } rows.mc = nil @@ -1140,14 +1145,14 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { } // Convert to byte-coded string - switch rows.rs.columns[i].fieldType { + switch rows.columns[i].fieldType { case fieldTypeNULL: dest[i] = nil continue // Numeric Types case fieldTypeTiny: - if rows.rs.columns[i].flags&flagUnsigned != 0 { + if rows.columns[i].flags&flagUnsigned != 0 { dest[i] = int64(data[pos]) } else { dest[i] = int64(int8(data[pos])) @@ -1156,7 +1161,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeShort, fieldTypeYear: - if rows.rs.columns[i].flags&flagUnsigned != 0 { + if rows.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]))) @@ -1165,7 +1170,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeInt24, fieldTypeLong: - if rows.rs.columns[i].flags&flagUnsigned != 0 { + if rows.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]))) @@ -1174,7 +1179,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeLongLong: - if rows.rs.columns[i].flags&flagUnsigned != 0 { + if rows.columns[i].flags&flagUnsigned != 0 { val := binary.LittleEndian.Uint64(data[pos : pos+8]) if val > math.MaxInt64 { dest[i] = uint64ToString(val) @@ -1188,7 +1193,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { continue case fieldTypeFloat: - dest[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4])) + dest[i] = float32(math.Float32frombits(binary.LittleEndian.Uint32(data[pos : pos+4]))) pos += 4 continue @@ -1228,10 +1233,10 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { case isNull: dest[i] = nil continue - case rows.rs.columns[i].fieldType == fieldTypeTime: + case rows.columns[i].fieldType == fieldTypeTime: // database/sql does not support an equivalent to TIME, return a string var dstlen uint8 - switch decimals := rows.rs.columns[i].decimals; decimals { + switch decimals := rows.columns[i].decimals; decimals { case 0x00, 0x1f: dstlen = 8 case 1, 2, 3, 4, 5, 6: @@ -1239,7 +1244,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { default: return fmt.Errorf( "protocol error, illegal decimals value %d", - rows.rs.columns[i].decimals, + rows.columns[i].decimals, ) } dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true) @@ -1247,10 +1252,10 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc) default: var dstlen uint8 - if rows.rs.columns[i].fieldType == fieldTypeDate { + if rows.columns[i].fieldType == fieldTypeDate { dstlen = 10 } else { - switch decimals := rows.rs.columns[i].decimals; decimals { + switch decimals := rows.columns[i].decimals; decimals { case 0x00, 0x1f: dstlen = 19 case 1, 2, 3, 4, 5, 6: @@ -1258,7 +1263,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { default: return fmt.Errorf( "protocol error, illegal decimals value %d", - rows.rs.columns[i].decimals, + rows.columns[i].decimals, ) } } @@ -1274,7 +1279,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { // Please report if this happens! default: - return fmt.Errorf("unknown field type %d", rows.rs.columns[i].fieldType) + return fmt.Errorf("unknown field type %d", rows.columns[i].fieldType) } } diff --git a/vendor/github.com/go-sql-driver/mysql/packets_test.go b/vendor/github.com/go-sql-driver/mysql/packets_test.go index b1d64f5c7..98404586a 100644 --- a/vendor/github.com/go-sql-driver/mysql/packets_test.go +++ b/vendor/github.com/go-sql-driver/mysql/packets_test.go @@ -101,7 +101,7 @@ func TestReadPacketSingleByte(t *testing.T) { t.Fatal(err) } if len(packet) != 1 { - t.Fatalf("unexpected packet length: expected %d, got %d", 1, len(packet)) + t.Fatalf("unexpected packet lenght: expected %d, got %d", 1, len(packet)) } if packet[0] != 0xff { t.Fatalf("unexpected packet content: expected %x, got %x", 0xff, packet[0]) @@ -171,7 +171,7 @@ func TestReadPacketSplit(t *testing.T) { t.Fatal(err) } if len(packet) != maxPacketSize { - t.Fatalf("unexpected packet length: expected %d, got %d", maxPacketSize, len(packet)) + t.Fatalf("unexpected packet lenght: expected %d, got %d", maxPacketSize, len(packet)) } if packet[0] != 0x11 { t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) @@ -205,7 +205,7 @@ func TestReadPacketSplit(t *testing.T) { t.Fatal(err) } if len(packet) != 2*maxPacketSize { - t.Fatalf("unexpected packet length: expected %d, got %d", 2*maxPacketSize, len(packet)) + t.Fatalf("unexpected packet lenght: expected %d, got %d", 2*maxPacketSize, len(packet)) } if packet[0] != 0x11 { t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) @@ -231,7 +231,7 @@ func TestReadPacketSplit(t *testing.T) { t.Fatal(err) } if len(packet) != maxPacketSize+42 { - t.Fatalf("unexpected packet length: expected %d, got %d", maxPacketSize+42, len(packet)) + t.Fatalf("unexpected packet lenght: expected %d, got %d", maxPacketSize+42, len(packet)) } if packet[0] != 0x11 { t.Fatalf("unexpected payload start: expected %x, got %x", 0x11, packet[0]) diff --git a/vendor/github.com/go-sql-driver/mysql/rows.go b/vendor/github.com/go-sql-driver/mysql/rows.go index 13905e216..c08255eee 100644 --- a/vendor/github.com/go-sql-driver/mysql/rows.go +++ b/vendor/github.com/go-sql-driver/mysql/rows.go @@ -21,15 +21,9 @@ type mysqlField struct { decimals byte } -type resultSet struct { - columns []mysqlField - columnNames []string - done bool -} - type mysqlRows struct { - mc *mysqlConn - rs resultSet + mc *mysqlConn + columns []mysqlField } type binaryRows struct { @@ -40,31 +34,27 @@ type textRows struct { mysqlRows } -func (rows *mysqlRows) Columns() []string { - if rows.rs.columnNames != nil { - return rows.rs.columnNames - } +type emptyRows struct{} - columns := make([]string, len(rows.rs.columns)) +func (rows *mysqlRows) Columns() []string { + columns := make([]string, len(rows.columns)) if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias { for i := range columns { - if tableName := rows.rs.columns[i].tableName; len(tableName) > 0 { - columns[i] = tableName + "." + rows.rs.columns[i].name + if tableName := rows.columns[i].tableName; len(tableName) > 0 { + columns[i] = tableName + "." + rows.columns[i].name } else { - columns[i] = rows.rs.columns[i].name + columns[i] = rows.columns[i].name } } } else { for i := range columns { - columns[i] = rows.rs.columns[i].name + columns[i] = rows.columns[i].name } } - - rows.rs.columnNames = columns return columns } -func (rows *mysqlRows) Close() (err error) { +func (rows *mysqlRows) Close() error { mc := rows.mc if mc == nil { return nil @@ -74,9 +64,7 @@ func (rows *mysqlRows) Close() (err error) { } // Remove unread packets from stream - if !rows.rs.done { - err = mc.readUntilEOF() - } + err := mc.readUntilEOF() if err == nil { if err = mc.discardResults(); err != nil { return err @@ -87,62 +75,6 @@ func (rows *mysqlRows) Close() (err error) { return err } -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 rows.mc.netConn == nil { - return 0, ErrInvalidConn - } - - // Remove unread packets from stream - if !rows.rs.done { - if err := rows.mc.readUntilEOF(); err != nil { - return 0, err - } - rows.rs.done = true - } - - if !rows.HasNextResultSet() { - rows.mc = nil - return 0, io.EOF - } - rows.rs = resultSet{} - return rows.mc.readResultSetHeaderPacket() -} - -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 { @@ -155,16 +87,6 @@ func (rows *binaryRows) Next(dest []driver.Value) error { return io.EOF } -func (rows *textRows) NextResultSet() (err error) { - resLen, err := rows.nextNotEmptyResultSet() - if err != nil { - return err - } - - rows.rs.columns, err = rows.mc.readColumns(resLen) - return err -} - func (rows *textRows) Next(dest []driver.Value) error { if mc := rows.mc; mc != nil { if mc.netConn == nil { @@ -176,3 +98,15 @@ func (rows *textRows) Next(dest []driver.Value) error { } return io.EOF } + +func (rows emptyRows) Columns() []string { + return nil +} + +func (rows emptyRows) Close() error { + return nil +} + +func (rows emptyRows) Next(dest []driver.Value) error { + return io.EOF +} diff --git a/vendor/github.com/go-sql-driver/mysql/statement.go b/vendor/github.com/go-sql-driver/mysql/statement.go index e5071276a..7f9b04585 100644 --- a/vendor/github.com/go-sql-driver/mysql/statement.go +++ b/vendor/github.com/go-sql-driver/mysql/statement.go @@ -11,7 +11,6 @@ package mysql import ( "database/sql/driver" "fmt" - "io" "reflect" "strconv" ) @@ -20,6 +19,7 @@ type mysqlStmt struct { mc *mysqlConn id uint32 paramCount int + columns []mysqlField // cached from the first query } func (stmt *mysqlStmt) Close() error { @@ -62,30 +62,26 @@ func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { // Read Result resLen, err := mc.readResultSetHeaderPacket() - if err != nil { - return nil, err - } - - if resLen > 0 { - // Columns - if err = mc.readUntilEOF(); err != nil { - return nil, err + if err == nil { + if resLen > 0 { + // Columns + err = mc.readUntilEOF() + if err != nil { + return nil, err + } + + // Rows + err = mc.readUntilEOF() } - - // Rows - if err := mc.readUntilEOF(); err != nil { - return nil, err + if err == nil { + return &mysqlResult{ + affectedRows: int64(mc.affectedRows), + insertId: int64(mc.insertId), + }, nil } } - if err := mc.discardResults(); err != nil { - return nil, err - } - - return &mysqlResult{ - affectedRows: int64(mc.affectedRows), - insertId: int64(mc.insertId), - }, nil + return nil, err } func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { @@ -111,15 +107,14 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { if resLen > 0 { rows.mc = mc - 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 + // 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() } } -- cgit v1.2.3-1-g7c22