Update dependencies and tests
This commit updates the dependencies, vendor files and updates tests to take into account changes to the DB driver. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
069bdd8b6b
commit
97d03dd38d
693 changed files with 86307 additions and 28214 deletions
16
vendor/github.com/go-sql-driver/mysql/AUTHORS
generated
vendored
16
vendor/github.com/go-sql-driver/mysql/AUTHORS
generated
vendored
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
Aaron Hopkins <go-sql-driver at die.net>
|
||||
Achille Roussel <achille.roussel at gmail.com>
|
||||
Aidan <aidan.liu at pingcap.com>
|
||||
Alex Snast <alexsn at fb.com>
|
||||
Alexey Palazhchenko <alexey.palazhchenko at gmail.com>
|
||||
Andrew Reid <andrew.reid at tixtrack.com>
|
||||
|
|
@ -20,12 +21,14 @@ Animesh Ray <mail.rayanimesh at gmail.com>
|
|||
Arne Hormann <arnehormann at gmail.com>
|
||||
Ariel Mashraki <ariel at mashraki.co.il>
|
||||
Asta Xie <xiemengjun at gmail.com>
|
||||
Brian Hendriks <brian at dolthub.com>
|
||||
Bulat Gaifullin <gaifullinbf at gmail.com>
|
||||
Caine Jette <jette at alum.mit.edu>
|
||||
Carlos Nieto <jose.carlos at menteslibres.net>
|
||||
Chris Kirkland <chriskirkland at github.com>
|
||||
Chris Moos <chris at tech9computers.com>
|
||||
Craig Wilson <craiggwilson at gmail.com>
|
||||
Daemonxiao <735462752 at qq.com>
|
||||
Daniel Montoya <dsmontoyam at gmail.com>
|
||||
Daniel Nichter <nil at codenode.com>
|
||||
Daniël van Eeden <git at myname.nl>
|
||||
|
|
@ -33,9 +36,11 @@ Dave Protasowski <dprotaso at gmail.com>
|
|||
DisposaBoy <disposaboy at dby.me>
|
||||
Egor Smolyakov <egorsmkv at gmail.com>
|
||||
Erwan Martin <hello at erwan.io>
|
||||
Evan Elias <evan at skeema.net>
|
||||
Evan Shaw <evan at vendhq.com>
|
||||
Frederick Mayle <frederickmayle at gmail.com>
|
||||
Gustavo Kristic <gkristic at gmail.com>
|
||||
Gusted <postmaster at gusted.xyz>
|
||||
Hajime Nakagami <nakagami at gmail.com>
|
||||
Hanno Braun <mail at hannobraun.com>
|
||||
Henri Yandell <flamefew at gmail.com>
|
||||
|
|
@ -47,8 +52,11 @@ INADA Naoki <songofacandy at gmail.com>
|
|||
Jacek Szwec <szwec.jacek at gmail.com>
|
||||
James Harr <james.harr at gmail.com>
|
||||
Janek Vedock <janekvedock at comcast.net>
|
||||
Jason Ng <oblitorum at gmail.com>
|
||||
Jean-Yves Pellé <jy at pelle.link>
|
||||
Jeff Hodges <jeff at somethingsimilar.com>
|
||||
Jeffrey Charles <jeffreycharles at gmail.com>
|
||||
Jennifer Purevsuren <jennifer at dolthub.com>
|
||||
Jerome Meyer <jxmeyer at gmail.com>
|
||||
Jiajia Zhong <zhong2plus at gmail.com>
|
||||
Jian Zhen <zhenjl at gmail.com>
|
||||
|
|
@ -74,9 +82,11 @@ Maciej Zimnoch <maciej.zimnoch at codilime.com>
|
|||
Michael Woolnough <michael.woolnough at gmail.com>
|
||||
Nathanial Murphy <nathanial.murphy at gmail.com>
|
||||
Nicola Peduzzi <thenikso at gmail.com>
|
||||
Oliver Bone <owbone at github.com>
|
||||
Olivier Mengué <dolmen at cpan.org>
|
||||
oscarzhao <oscarzhaosl at gmail.com>
|
||||
Paul Bonser <misterpib at gmail.com>
|
||||
Paulius Lozys <pauliuslozys at gmail.com>
|
||||
Peter Schultz <peter.schultz at classmarkets.com>
|
||||
Phil Porada <philporada at gmail.com>
|
||||
Rebecca Chin <rchin at pivotal.io>
|
||||
|
|
@ -95,6 +105,7 @@ Stan Putrya <root.vagner at gmail.com>
|
|||
Stanley Gunawan <gunawan.stanley at gmail.com>
|
||||
Steven Hartland <steven.hartland at multiplay.co.uk>
|
||||
Tan Jinhua <312841925 at qq.com>
|
||||
Tetsuro Aoki <t.aoki1130 at gmail.com>
|
||||
Thomas Wodarek <wodarekwebpage at gmail.com>
|
||||
Tim Ruffles <timruffles at gmail.com>
|
||||
Tom Jenkinson <tom at tjenkinson.me>
|
||||
|
|
@ -104,6 +115,7 @@ Xiangyu Hu <xiangyu.hu at outlook.com>
|
|||
Xiaobing Jiang <s7v7nislands at gmail.com>
|
||||
Xiuming Chen <cc at cxm.cc>
|
||||
Xuehong Chan <chanxuehong at gmail.com>
|
||||
Zhang Xiang <angwerzx at 126.com>
|
||||
Zhenye Xie <xiezhenye at gmail.com>
|
||||
Zhixin Wen <john.wenzhixin at gmail.com>
|
||||
Ziheng Lyu <zihenglv at gmail.com>
|
||||
|
|
@ -113,14 +125,18 @@ Ziheng Lyu <zihenglv at gmail.com>
|
|||
Barracuda Networks, Inc.
|
||||
Counting Ltd.
|
||||
DigitalOcean Inc.
|
||||
Dolthub Inc.
|
||||
dyves labs AG
|
||||
Facebook Inc.
|
||||
GitHub Inc.
|
||||
Google Inc.
|
||||
InfoSum Ltd.
|
||||
Keybase Inc.
|
||||
Microsoft Corp.
|
||||
Multiplay Ltd.
|
||||
Percona LLC
|
||||
PingCAP Inc.
|
||||
Pivotal Inc.
|
||||
Shattered Silicon Ltd.
|
||||
Stripe Inc.
|
||||
Zendesk Inc.
|
||||
|
|
|
|||
48
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md
generated
vendored
48
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md
generated
vendored
|
|
@ -1,3 +1,45 @@
|
|||
## Version 1.8.1 (2024-03-26)
|
||||
|
||||
Bugfixes:
|
||||
|
||||
- fix race condition when context is canceled in [#1562](https://github.com/go-sql-driver/mysql/pull/1562) and [#1570](https://github.com/go-sql-driver/mysql/pull/1570)
|
||||
|
||||
## Version 1.8.0 (2024-03-09)
|
||||
|
||||
Major Changes:
|
||||
|
||||
- Use `SET NAMES charset COLLATE collation`. by @methane in [#1437](https://github.com/go-sql-driver/mysql/pull/1437)
|
||||
- Older go-mysql-driver used `collation_id` in the handshake packet. But it caused collation mismatch in some situation.
|
||||
- If you don't specify charset nor collation, go-mysql-driver sends `SET NAMES utf8mb4` for new connection. This uses server's default collation for utf8mb4.
|
||||
- If you specify charset, go-mysql-driver sends `SET NAMES <charset>`. This uses the server's default collation for `<charset>`.
|
||||
- If you specify collation and/or charset, go-mysql-driver sends `SET NAMES charset COLLATE collation`.
|
||||
- PathEscape dbname in DSN. by @methane in [#1432](https://github.com/go-sql-driver/mysql/pull/1432)
|
||||
- This is backward incompatible in rare case. Check your DSN.
|
||||
- Drop Go 1.13-17 support by @methane in [#1420](https://github.com/go-sql-driver/mysql/pull/1420)
|
||||
- Use Go 1.18+
|
||||
- Parse numbers on text protocol too by @methane in [#1452](https://github.com/go-sql-driver/mysql/pull/1452)
|
||||
- When text protocol is used, go-mysql-driver passed bare `[]byte` to database/sql for avoid unnecessary allocation and conversion.
|
||||
- If user specified `*any` to `Scan()`, database/sql passed the `[]byte` into the target variable.
|
||||
- This confused users because most user doesn't know when text/binary protocol used.
|
||||
- go-mysql-driver 1.8 converts integer/float values into int64/double even in text protocol. This doesn't increase allocation compared to `[]byte` and conversion cost is negatable.
|
||||
- New options start using the Functional Option Pattern to avoid increasing technical debt in the Config object. Future version may introduce Functional Option for existing options, but not for now.
|
||||
- Make TimeTruncate functional option by @methane in [1552](https://github.com/go-sql-driver/mysql/pull/1552)
|
||||
- Add BeforeConnect callback to configuration object by @ItalyPaleAle in [#1469](https://github.com/go-sql-driver/mysql/pull/1469)
|
||||
|
||||
|
||||
Other changes:
|
||||
|
||||
- Adding DeregisterDialContext to prevent memory leaks with dialers we don't need anymore by @jypelle in https://github.com/go-sql-driver/mysql/pull/1422
|
||||
- Make logger configurable per connection by @frozenbonito in https://github.com/go-sql-driver/mysql/pull/1408
|
||||
- Fix ColumnType.DatabaseTypeName for mediumint unsigned by @evanelias in https://github.com/go-sql-driver/mysql/pull/1428
|
||||
- Add connection attributes by @Daemonxiao in https://github.com/go-sql-driver/mysql/pull/1389
|
||||
- Stop `ColumnTypeScanType()` from returning `sql.RawBytes` by @methane in https://github.com/go-sql-driver/mysql/pull/1424
|
||||
- Exec() now provides access to status of multiple statements. by @mherr-google in https://github.com/go-sql-driver/mysql/pull/1309
|
||||
- Allow to change (or disable) the default driver name for registration by @dolmen in https://github.com/go-sql-driver/mysql/pull/1499
|
||||
- Add default connection attribute '_server_host' by @oblitorum in https://github.com/go-sql-driver/mysql/pull/1506
|
||||
- QueryUnescape DSN ConnectionAttribute value by @zhangyangyu in https://github.com/go-sql-driver/mysql/pull/1470
|
||||
- Add client_ed25519 authentication by @Gusted in https://github.com/go-sql-driver/mysql/pull/1518
|
||||
|
||||
## Version 1.7.1 (2023-04-25)
|
||||
|
||||
Changes:
|
||||
|
|
@ -162,7 +204,7 @@ 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)
|
||||
- Placeholder interpolation, can be activated 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)
|
||||
|
|
@ -206,7 +248,7 @@ Changes:
|
|||
- Also exported the MySQLWarning type
|
||||
- mysqlConn.Close returns the first error encountered instead of ignoring all errors
|
||||
- writePacket() automatically writes the packet size to the header
|
||||
- readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets
|
||||
- readPacket() uses an iterative approach instead of the recursive approach to merge split packets
|
||||
|
||||
New Features:
|
||||
|
||||
|
|
@ -254,7 +296,7 @@ Bugfixes:
|
|||
|
||||
- Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification
|
||||
- Convert to DB timezone when inserting `time.Time`
|
||||
- Splitted packets (more than 16MB) are now merged correctly
|
||||
- Split packets (more than 16MB) are now merged correctly
|
||||
- Fixed false positive `io.EOF` errors when the data was fully read
|
||||
- Avoid panics on reuse of closed connections
|
||||
- Fixed empty string producing false nil values
|
||||
|
|
|
|||
78
vendor/github.com/go-sql-driver/mysql/README.md
generated
vendored
78
vendor/github.com/go-sql-driver/mysql/README.md
generated
vendored
|
|
@ -40,15 +40,23 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac
|
|||
* Optional placeholder interpolation
|
||||
|
||||
## Requirements
|
||||
* Go 1.13 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+)
|
||||
|
||||
* Go 1.19 or higher. We aim to support the 3 latest versions of Go.
|
||||
* MySQL (5.7+) and MariaDB (10.3+) are supported.
|
||||
* [TiDB](https://github.com/pingcap/tidb) is supported by PingCAP.
|
||||
* Do not ask questions about TiDB in our issue tracker or forum.
|
||||
* [Document](https://docs.pingcap.com/tidb/v6.1/dev-guide-sample-application-golang)
|
||||
* [Forum](https://ask.pingcap.com/)
|
||||
* go-mysql would work with Percona Server, Google CloudSQL or Sphinx (2.2.3+).
|
||||
* Maintainers won't support them. Do not expect issues are investigated and resolved by maintainers.
|
||||
* Investigate issues yourself and please send a pull request to fix it.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## Installation
|
||||
Simple install the package to your [$GOPATH](https://github.com/golang/go/wiki/GOPATH "GOPATH") with the [go tool](https://golang.org/cmd/go/ "go command") from shell:
|
||||
```bash
|
||||
$ go get -u github.com/go-sql-driver/mysql
|
||||
go get -u github.com/go-sql-driver/mysql
|
||||
```
|
||||
Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`.
|
||||
|
||||
|
|
@ -114,6 +122,12 @@ This has the same effect as an empty DSN string:
|
|||
|
||||
```
|
||||
|
||||
`dbname` is escaped by [PathEscape()](https://pkg.go.dev/net/url#PathEscape) since v1.8.0. If your database name is `dbname/withslash`, it becomes:
|
||||
|
||||
```
|
||||
/dbname%2Fwithslash
|
||||
```
|
||||
|
||||
Alternatively, [Config.FormatDSN](https://godoc.org/github.com/go-sql-driver/mysql#Config.FormatDSN) can be used to create a DSN string by filling a struct.
|
||||
|
||||
#### Password
|
||||
|
|
@ -121,7 +135,7 @@ 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.
|
||||
In general you should use an Unix domain socket if available and TCP otherwise for best performance.
|
||||
In general you should use a Unix domain socket if available and TCP otherwise for best performance.
|
||||
|
||||
#### Address
|
||||
For TCP and UDP networks, addresses have the form `host[:port]`.
|
||||
|
|
@ -145,7 +159,7 @@ Default: false
|
|||
```
|
||||
|
||||
`allowAllFiles=true` disables the file allowlist for `LOAD DATA LOCAL INFILE` and allows *all* files.
|
||||
[*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)
|
||||
[*Might be insecure!*](https://dev.mysql.com/doc/refman/8.0/en/load-data.html#load-data-local)
|
||||
|
||||
##### `allowCleartextPasswords`
|
||||
|
||||
|
|
@ -194,10 +208,9 @@ Valid Values: <name>
|
|||
Default: none
|
||||
```
|
||||
|
||||
Sets the charset used for client-server interaction (`"SET NAMES <value>"`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset failes. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`).
|
||||
Sets the charset used for client-server interaction (`"SET NAMES <value>"`). If multiple charsets are set (separated by a comma), the following charset is used if setting the charset fails. This enables for example support for `utf8mb4` ([introduced in MySQL 5.5.3](http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html)) with fallback to `utf8` for older servers (`charset=utf8mb4,utf8`).
|
||||
|
||||
Usage of the `charset` parameter is discouraged because it issues additional queries to the server.
|
||||
Unless you need the fallback behavior, please use `collation` instead.
|
||||
See also [Unicode Support](#unicode-support).
|
||||
|
||||
##### `checkConnLiveness`
|
||||
|
||||
|
|
@ -226,6 +239,7 @@ The default collation (`utf8mb4_general_ci`) is supported from MySQL 5.5. You s
|
|||
|
||||
Collations for charset "ucs2", "utf16", "utf16le", and "utf32" can not be used ([ref](https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html#charset-connection-impermissible-client-charset)).
|
||||
|
||||
See also [Unicode Support](#unicode-support).
|
||||
|
||||
##### `clientFoundRows`
|
||||
|
||||
|
|
@ -279,6 +293,15 @@ Note that this sets the location for time.Time values but does not change MySQL'
|
|||
|
||||
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`.
|
||||
|
||||
##### `timeTruncate`
|
||||
|
||||
```
|
||||
Type: duration
|
||||
Default: 0
|
||||
```
|
||||
|
||||
[Truncate time values](https://pkg.go.dev/time#Duration.Truncate) to the specified duration. The value must be a decimal number with a unit suffix (*"ms"*, *"s"*, *"m"*, *"h"*), such as *"30s"*, *"0.5m"* or *"1m30s"*.
|
||||
|
||||
##### `maxAllowedPacket`
|
||||
```
|
||||
Type: decimal number
|
||||
|
|
@ -295,9 +318,25 @@ Valid Values: true, false
|
|||
Default: false
|
||||
```
|
||||
|
||||
Allow multiple statements in one query. While this allows batch queries, it also greatly increases the risk of SQL injections. Only the result of the first query is returned, all other results are silently discarded.
|
||||
Allow multiple statements in one query. This can be used to bach multiple queries. Use [Rows.NextResultSet()](https://pkg.go.dev/database/sql#Rows.NextResultSet) to get result of the second and subsequent queries.
|
||||
|
||||
When `multiStatements` is used, `?` parameters must only be used in the first statement.
|
||||
When `multiStatements` is used, `?` parameters must only be used in the first statement. [interpolateParams](#interpolateparams) can be used to avoid this limitation unless prepared statement is used explicitly.
|
||||
|
||||
It's possible to access the last inserted ID and number of affected rows for multiple statements by using `sql.Conn.Raw()` and the `mysql.Result`. For example:
|
||||
|
||||
```go
|
||||
conn, _ := db.Conn(ctx)
|
||||
conn.Raw(func(conn any) error {
|
||||
ex := conn.(driver.Execer)
|
||||
res, err := ex.Exec(`
|
||||
UPDATE point SET x = 1 WHERE y = 2;
|
||||
UPDATE point SET x = 2 WHERE y = 3;
|
||||
`, nil)
|
||||
// Both slices have 2 elements.
|
||||
log.Print(res.(mysql.Result).AllRowsAffected())
|
||||
log.Print(res.(mysql.Result).AllLastInsertIds())
|
||||
})
|
||||
```
|
||||
|
||||
##### `parseTime`
|
||||
|
||||
|
|
@ -393,6 +432,15 @@ 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"*.
|
||||
|
||||
##### `connectionAttributes`
|
||||
|
||||
```
|
||||
Type: comma-delimited string of user-defined "key:value" pairs
|
||||
Valid Values: (<name1>:<value1>,<name2>:<value2>,...)
|
||||
Default: none
|
||||
```
|
||||
|
||||
[Connection attributes](https://dev.mysql.com/doc/refman/8.0/en/performance-schema-connection-attribute-tables.html) are key-value pairs that application programs can pass to the server at connect time.
|
||||
|
||||
##### System Variables
|
||||
|
||||
|
|
@ -465,7 +513,7 @@ user:password@/
|
|||
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. All Unsigned database type names will be returned `UNSIGNED ` with `INT`, `TINYINT`, `SMALLINT`, `BIGINT`.
|
||||
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. All Unsigned database type names will be returned `UNSIGNED ` with `INT`, `TINYINT`, `SMALLINT`, `MEDIUMINT`, `BIGINT`.
|
||||
|
||||
## `context.Context` Support
|
||||
Go 1.8 added `database/sql` support for `context.Context`. This driver supports query timeouts and cancellation via contexts.
|
||||
|
|
@ -478,7 +526,7 @@ For this feature you need direct access to the package. Therefore you must chang
|
|||
import "github.com/go-sql-driver/mysql"
|
||||
```
|
||||
|
||||
Files must be explicitly allowed by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the allowlist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](http://dev.mysql.com/doc/refman/5.7/en/load-data-local.html)).
|
||||
Files must be explicitly allowed by registering them with `mysql.RegisterLocalFile(filepath)` (recommended) or the allowlist check must be deactivated by using the DSN parameter `allowAllFiles=true` ([*Might be insecure!*](https://dev.mysql.com/doc/refman/8.0/en/load-data.html#load-data-local)).
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -496,9 +544,11 @@ However, many want to scan MySQL `DATE` and `DATETIME` values into `time.Time` v
|
|||
### Unicode support
|
||||
Since version 1.5 Go-MySQL-Driver automatically uses the collation ` utf8mb4_general_ci` by default.
|
||||
|
||||
Other collations / charsets can be set using the [`collation`](#collation) DSN parameter.
|
||||
Other charsets / collations can be set using the [`charset`](#charset) or [`collation`](#collation) DSN parameter.
|
||||
|
||||
Version 1.0 of the driver recommended adding `&charset=utf8` (alias for `SET NAMES utf8`) to the DSN to enable proper UTF-8 support. This is not necessary anymore. The [`collation`](#collation) parameter should be preferred to set another collation / charset than the default.
|
||||
- When only the `charset` is specified, the `SET NAMES <charset>` query is sent and the server's default collation is used.
|
||||
- When both the `charset` and `collation` are specified, the `SET NAMES <charset> COLLATE <collation>` query is sent.
|
||||
- When only the `collation` is specified, the collation is specified in the protocol handshake and the `SET NAMES` query is not sent. This can save one roundtrip, but note that the server may ignore the specified collation silently and use the server's default charset/collation instead.
|
||||
|
||||
See http://dev.mysql.com/doc/refman/8.0/en/charset-unicode.html for more details on MySQL's Unicode support.
|
||||
|
||||
|
|
|
|||
63
vendor/github.com/go-sql-driver/mysql/auth.go
generated
vendored
63
vendor/github.com/go-sql-driver/mysql/auth.go
generated
vendored
|
|
@ -13,10 +13,13 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"filippo.io/edwards25519"
|
||||
)
|
||||
|
||||
// server pub keys registry
|
||||
|
|
@ -33,7 +36,7 @@ var (
|
|||
// 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")
|
||||
// data, err := os.ReadFile("mykey.pem")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
|
|
@ -225,6 +228,44 @@ func encryptPassword(password string, seed []byte, pub *rsa.PublicKey) ([]byte,
|
|||
return rsa.EncryptOAEP(sha1, rand.Reader, pub, plain, nil)
|
||||
}
|
||||
|
||||
// authEd25519 does ed25519 authentication used by MariaDB.
|
||||
func authEd25519(scramble []byte, password string) ([]byte, error) {
|
||||
// Derived from https://github.com/MariaDB/server/blob/d8e6bb00888b1f82c031938f4c8ac5d97f6874c3/plugin/auth_ed25519/ref10/sign.c
|
||||
// Code style is from https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/crypto/ed25519/ed25519.go;l=207
|
||||
h := sha512.Sum512([]byte(password))
|
||||
|
||||
s, err := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
A := (&edwards25519.Point{}).ScalarBaseMult(s)
|
||||
|
||||
mh := sha512.New()
|
||||
mh.Write(h[32:])
|
||||
mh.Write(scramble)
|
||||
messageDigest := mh.Sum(nil)
|
||||
r, err := edwards25519.NewScalar().SetUniformBytes(messageDigest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
R := (&edwards25519.Point{}).ScalarBaseMult(r)
|
||||
|
||||
kh := sha512.New()
|
||||
kh.Write(R.Bytes())
|
||||
kh.Write(A.Bytes())
|
||||
kh.Write(scramble)
|
||||
hramDigest := kh.Sum(nil)
|
||||
k, err := edwards25519.NewScalar().SetUniformBytes(hramDigest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
S := k.MultiplyAdd(k, s, r)
|
||||
|
||||
return append(R.Bytes(), S.Bytes()...), nil
|
||||
}
|
||||
|
||||
func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) error {
|
||||
enc, err := encryptPassword(mc.cfg.Passwd, seed, pub)
|
||||
if err != nil {
|
||||
|
|
@ -290,8 +331,14 @@ func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) {
|
|||
enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
|
||||
return enc, err
|
||||
|
||||
case "client_ed25519":
|
||||
if len(authData) != 32 {
|
||||
return nil, ErrMalformPkt
|
||||
}
|
||||
return authEd25519(authData, mc.cfg.Passwd)
|
||||
|
||||
default:
|
||||
errLog.Print("unknown auth plugin:", plugin)
|
||||
mc.log("unknown auth plugin:", plugin)
|
||||
return nil, ErrUnknownPlugin
|
||||
}
|
||||
}
|
||||
|
|
@ -338,7 +385,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||
|
||||
switch plugin {
|
||||
|
||||
// https://insidemysql.com/preparing-your-community-connector-for-mysql-8-part-2-sha256/
|
||||
// https://dev.mysql.com/blog-archive/preparing-your-community-connector-for-mysql-8-part-2-sha256/
|
||||
case "caching_sha2_password":
|
||||
switch len(authData) {
|
||||
case 0:
|
||||
|
|
@ -346,7 +393,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||
case 1:
|
||||
switch authData[0] {
|
||||
case cachingSha2PasswordFastAuthSuccess:
|
||||
if err = mc.readResultOK(); err == nil {
|
||||
if err = mc.resultUnchanged().readResultOK(); err == nil {
|
||||
return nil // auth successful
|
||||
}
|
||||
|
||||
|
|
@ -376,13 +423,13 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||
}
|
||||
|
||||
if data[0] != iAuthMoreData {
|
||||
return fmt.Errorf("unexpect resp from server for caching_sha2_password perform full authentication")
|
||||
return fmt.Errorf("unexpected resp from server for caching_sha2_password, perform full authentication")
|
||||
}
|
||||
|
||||
// parse public key
|
||||
block, rest := pem.Decode(data[1:])
|
||||
if block == nil {
|
||||
return fmt.Errorf("No Pem data found, data: %s", rest)
|
||||
return fmt.Errorf("no pem data found, data: %s", rest)
|
||||
}
|
||||
pkix, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
|
|
@ -397,7 +444,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
return mc.readResultOK()
|
||||
return mc.resultUnchanged().readResultOK()
|
||||
|
||||
default:
|
||||
return ErrMalformPkt
|
||||
|
|
@ -426,7 +473,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mc.readResultOK()
|
||||
return mc.resultUnchanged().readResultOK()
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
|||
2
vendor/github.com/go-sql-driver/mysql/collations.go
generated
vendored
2
vendor/github.com/go-sql-driver/mysql/collations.go
generated
vendored
|
|
@ -9,7 +9,7 @@
|
|||
package mysql
|
||||
|
||||
const defaultCollation = "utf8mb4_general_ci"
|
||||
const binaryCollation = "binary"
|
||||
const binaryCollationID = 63
|
||||
|
||||
// A list of available collations mapped to the internal ID.
|
||||
// To update this map use the following MySQL query:
|
||||
|
|
|
|||
100
vendor/github.com/go-sql-driver/mysql/connection.go
generated
vendored
100
vendor/github.com/go-sql-driver/mysql/connection.go
generated
vendored
|
|
@ -23,10 +23,10 @@ import (
|
|||
type mysqlConn struct {
|
||||
buf buffer
|
||||
netConn net.Conn
|
||||
rawConn net.Conn // underlying connection when netConn is TLS connection.
|
||||
affectedRows uint64
|
||||
insertId uint64
|
||||
rawConn net.Conn // underlying connection when netConn is TLS connection.
|
||||
result mysqlResult // managed by clearResult() and handleOkPacket().
|
||||
cfg *Config
|
||||
connector *connector
|
||||
maxAllowedPacket int
|
||||
maxWriteSize int
|
||||
writeTimeout time.Duration
|
||||
|
|
@ -34,7 +34,6 @@ type mysqlConn struct {
|
|||
status statusFlag
|
||||
sequence uint8
|
||||
parseTime bool
|
||||
reset bool // set when the Go SQL package calls ResetSession
|
||||
|
||||
// for context support (Go 1.8+)
|
||||
watching bool
|
||||
|
|
@ -45,17 +44,27 @@ type mysqlConn struct {
|
|||
closed atomicBool // set when conn is closed, before closech is closed
|
||||
}
|
||||
|
||||
// Helper function to call per-connection logger.
|
||||
func (mc *mysqlConn) log(v ...any) {
|
||||
mc.cfg.Logger.Print(v...)
|
||||
}
|
||||
|
||||
// Handles parameters set in DSN after the connection is established
|
||||
func (mc *mysqlConn) handleParams() (err error) {
|
||||
var cmdSet strings.Builder
|
||||
|
||||
for param, val := range mc.cfg.Params {
|
||||
switch param {
|
||||
// Charset: character_set_connection, character_set_client, character_set_results
|
||||
case "charset":
|
||||
charsets := strings.Split(val, ",")
|
||||
for i := range charsets {
|
||||
for _, cs := range charsets {
|
||||
// ignore errors here - a charset may not exist
|
||||
err = mc.exec("SET NAMES " + charsets[i])
|
||||
if mc.cfg.Collation != "" {
|
||||
err = mc.exec("SET NAMES " + cs + " COLLATE " + mc.cfg.Collation)
|
||||
} else {
|
||||
err = mc.exec("SET NAMES " + cs)
|
||||
}
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
|
@ -68,7 +77,7 @@ func (mc *mysqlConn) handleParams() (err error) {
|
|||
default:
|
||||
if cmdSet.Len() == 0 {
|
||||
// Heuristic: 29 chars for each other key=value to reduce reallocations
|
||||
cmdSet.Grow(4 + len(param) + 1 + len(val) + 30*(len(mc.cfg.Params)-1))
|
||||
cmdSet.Grow(4 + len(param) + 3 + len(val) + 30*(len(mc.cfg.Params)-1))
|
||||
cmdSet.WriteString("SET ")
|
||||
} else {
|
||||
cmdSet.WriteString(", ")
|
||||
|
|
@ -105,7 +114,7 @@ func (mc *mysqlConn) Begin() (driver.Tx, error) {
|
|||
|
||||
func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) {
|
||||
if mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
var q string
|
||||
|
|
@ -128,7 +137,7 @@ func (mc *mysqlConn) Close() (err error) {
|
|||
}
|
||||
|
||||
mc.cleanup()
|
||||
|
||||
mc.clearResult()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -143,12 +152,16 @@ func (mc *mysqlConn) cleanup() {
|
|||
|
||||
// Makes cleanup idempotent
|
||||
close(mc.closech)
|
||||
if mc.netConn == nil {
|
||||
conn := mc.rawConn
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
if err := mc.netConn.Close(); err != nil {
|
||||
errLog.Print(err)
|
||||
if err := conn.Close(); err != nil {
|
||||
mc.log(err)
|
||||
}
|
||||
// This function can be called from multiple goroutines.
|
||||
// So we can not mc.clearResult() here.
|
||||
// Caller should do it if they are in safe goroutine.
|
||||
}
|
||||
|
||||
func (mc *mysqlConn) error() error {
|
||||
|
|
@ -163,14 +176,14 @@ func (mc *mysqlConn) error() error {
|
|||
|
||||
func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
|
||||
if mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
// Send command
|
||||
err := mc.writeCommandPacketStr(comStmtPrepare, query)
|
||||
if err != nil {
|
||||
// STMT_PREPARE is safe to retry. So we can return ErrBadConn here.
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +217,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
|
|||
buf, err := mc.buf.takeCompleteBuffer()
|
||||
if err != nil {
|
||||
// can not take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return "", ErrInvalidConn
|
||||
}
|
||||
buf = buf[:0]
|
||||
|
|
@ -246,7 +259,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
|
|||
buf = append(buf, "'0000-00-00'"...)
|
||||
} else {
|
||||
buf = append(buf, '\'')
|
||||
buf, err = appendDateTime(buf, v.In(mc.cfg.Loc))
|
||||
buf, err = appendDateTime(buf, v.In(mc.cfg.Loc), mc.cfg.timeTruncate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -296,7 +309,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.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
if len(args) != 0 {
|
||||
|
|
@ -310,28 +323,25 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err
|
|||
}
|
||||
query = prepared
|
||||
}
|
||||
mc.affectedRows = 0
|
||||
mc.insertId = 0
|
||||
|
||||
err := mc.exec(query)
|
||||
if err == nil {
|
||||
return &mysqlResult{
|
||||
affectedRows: int64(mc.affectedRows),
|
||||
insertId: int64(mc.insertId),
|
||||
}, err
|
||||
copied := mc.result
|
||||
return &copied, err
|
||||
}
|
||||
return nil, mc.markBadConn(err)
|
||||
}
|
||||
|
||||
// Internal function to execute commands
|
||||
func (mc *mysqlConn) exec(query string) error {
|
||||
handleOk := mc.clearResult()
|
||||
// Send command
|
||||
if err := mc.writeCommandPacketStr(comQuery, query); err != nil {
|
||||
return mc.markBadConn(err)
|
||||
}
|
||||
|
||||
// Read Result
|
||||
resLen, err := mc.readResultSetHeaderPacket()
|
||||
resLen, err := handleOk.readResultSetHeaderPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -348,7 +358,7 @@ func (mc *mysqlConn) exec(query string) error {
|
|||
}
|
||||
}
|
||||
|
||||
return mc.discardResults()
|
||||
return handleOk.discardResults()
|
||||
}
|
||||
|
||||
func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, error) {
|
||||
|
|
@ -356,8 +366,10 @@ func (mc *mysqlConn) Query(query string, args []driver.Value) (driver.Rows, erro
|
|||
}
|
||||
|
||||
func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error) {
|
||||
handleOk := mc.clearResult()
|
||||
|
||||
if mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
if len(args) != 0 {
|
||||
|
|
@ -376,7 +388,7 @@ func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error)
|
|||
if err == nil {
|
||||
// Read Result
|
||||
var resLen int
|
||||
resLen, err = mc.readResultSetHeaderPacket()
|
||||
resLen, err = handleOk.readResultSetHeaderPacket()
|
||||
if err == nil {
|
||||
rows := new(textRows)
|
||||
rows.mc = mc
|
||||
|
|
@ -404,12 +416,13 @@ func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error)
|
|||
// The returned byte slice is only valid until the next read
|
||||
func (mc *mysqlConn) getSystemVar(name string) ([]byte, error) {
|
||||
// Send command
|
||||
handleOk := mc.clearResult()
|
||||
if err := mc.writeCommandPacketStr(comQuery, "SELECT @@"+name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Read Result
|
||||
resLen, err := mc.readResultSetHeaderPacket()
|
||||
resLen, err := handleOk.readResultSetHeaderPacket()
|
||||
if err == nil {
|
||||
rows := new(textRows)
|
||||
rows.mc = mc
|
||||
|
|
@ -451,7 +464,7 @@ func (mc *mysqlConn) finish() {
|
|||
// Ping implements driver.Pinger interface
|
||||
func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
|
||||
if mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
mc.log(ErrInvalidConn)
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
|
||||
|
|
@ -460,11 +473,12 @@ func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
|
|||
}
|
||||
defer mc.finish()
|
||||
|
||||
handleOk := mc.clearResult()
|
||||
if err = mc.writeCommandPacket(comPing); err != nil {
|
||||
return mc.markBadConn(err)
|
||||
}
|
||||
|
||||
return mc.readResultOK()
|
||||
return handleOk.readResultOK()
|
||||
}
|
||||
|
||||
// BeginTx implements driver.ConnBeginTx interface
|
||||
|
|
@ -639,7 +653,31 @@ func (mc *mysqlConn) ResetSession(ctx context.Context) error {
|
|||
if mc.closed.Load() {
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
mc.reset = true
|
||||
|
||||
// Perform a stale connection check. We only perform this check for
|
||||
// the first query on a connection that has been checked out of the
|
||||
// connection pool: a fresh connection from the pool is more likely
|
||||
// to be stale, and it has not performed any previous writes that
|
||||
// could cause data corruption, so it's safe to return ErrBadConn
|
||||
// if the check fails.
|
||||
if mc.cfg.CheckConnLiveness {
|
||||
conn := mc.netConn
|
||||
if mc.rawConn != nil {
|
||||
conn = mc.rawConn
|
||||
}
|
||||
var err error
|
||||
if mc.cfg.ReadTimeout != 0 {
|
||||
err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout))
|
||||
}
|
||||
if err == nil {
|
||||
err = connCheck(conn)
|
||||
}
|
||||
if err != nil {
|
||||
mc.log("closing bad idle connection: ", err)
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
67
vendor/github.com/go-sql-driver/mysql/connector.go
generated
vendored
67
vendor/github.com/go-sql-driver/mysql/connector.go
generated
vendored
|
|
@ -12,10 +12,53 @@ import (
|
|||
"context"
|
||||
"database/sql/driver"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type connector struct {
|
||||
cfg *Config // immutable private copy.
|
||||
cfg *Config // immutable private copy.
|
||||
encodedAttributes string // Encoded connection attributes.
|
||||
}
|
||||
|
||||
func encodeConnectionAttributes(cfg *Config) string {
|
||||
connAttrsBuf := make([]byte, 0)
|
||||
|
||||
// default connection attributes
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrClientName)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrClientNameValue)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrOS)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrOSValue)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPlatform)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPlatformValue)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrPid)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, strconv.Itoa(os.Getpid()))
|
||||
serverHost, _, _ := net.SplitHostPort(cfg.Addr)
|
||||
if serverHost != "" {
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, connAttrServerHost)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, serverHost)
|
||||
}
|
||||
|
||||
// user-defined connection attributes
|
||||
for _, connAttr := range strings.Split(cfg.ConnectionAttributes, ",") {
|
||||
k, v, found := strings.Cut(connAttr, ":")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, k)
|
||||
connAttrsBuf = appendLengthEncodedString(connAttrsBuf, v)
|
||||
}
|
||||
|
||||
return string(connAttrsBuf)
|
||||
}
|
||||
|
||||
func newConnector(cfg *Config) *connector {
|
||||
encodedAttributes := encodeConnectionAttributes(cfg)
|
||||
return &connector{
|
||||
cfg: cfg,
|
||||
encodedAttributes: encodedAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
// Connect implements driver.Connector interface.
|
||||
|
|
@ -23,12 +66,23 @@ type connector struct {
|
|||
func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
|
||||
var err error
|
||||
|
||||
// Invoke beforeConnect if present, with a copy of the configuration
|
||||
cfg := c.cfg
|
||||
if c.cfg.beforeConnect != nil {
|
||||
cfg = c.cfg.Clone()
|
||||
err = c.cfg.beforeConnect(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// New mysqlConn
|
||||
mc := &mysqlConn{
|
||||
maxAllowedPacket: maxPacketSize,
|
||||
maxWriteSize: maxPacketSize - 1,
|
||||
closech: make(chan struct{}),
|
||||
cfg: c.cfg,
|
||||
cfg: cfg,
|
||||
connector: c,
|
||||
}
|
||||
mc.parseTime = mc.cfg.ParseTime
|
||||
|
||||
|
|
@ -48,18 +102,15 @@ func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||
nd := net.Dialer{Timeout: mc.cfg.Timeout}
|
||||
mc.netConn, err = nd.DialContext(ctx, mc.cfg.Net, mc.cfg.Addr)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc.rawConn = mc.netConn
|
||||
|
||||
// Enable TCP Keepalives on TCP connections
|
||||
if tc, ok := mc.netConn.(*net.TCPConn); ok {
|
||||
if err := tc.SetKeepAlive(true); err != nil {
|
||||
// Don't send COM_QUIT before handshake.
|
||||
mc.netConn.Close()
|
||||
mc.netConn = nil
|
||||
return nil, err
|
||||
c.cfg.Logger.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +143,7 @@ func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||
authResp, 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())
|
||||
c.cfg.Logger.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
|
||||
plugin = defaultAuthPlugin
|
||||
authResp, err = mc.auth(authData, plugin)
|
||||
if err != nil {
|
||||
|
|
|
|||
13
vendor/github.com/go-sql-driver/mysql/const.go
generated
vendored
13
vendor/github.com/go-sql-driver/mysql/const.go
generated
vendored
|
|
@ -8,12 +8,25 @@
|
|||
|
||||
package mysql
|
||||
|
||||
import "runtime"
|
||||
|
||||
const (
|
||||
defaultAuthPlugin = "mysql_native_password"
|
||||
defaultMaxAllowedPacket = 64 << 20 // 64 MiB. See https://github.com/go-sql-driver/mysql/issues/1355
|
||||
minProtocolVersion = 10
|
||||
maxPacketSize = 1<<24 - 1
|
||||
timeFormat = "2006-01-02 15:04:05.999999"
|
||||
|
||||
// Connection attributes
|
||||
// See https://dev.mysql.com/doc/refman/8.0/en/performance-schema-connection-attribute-tables.html#performance-schema-connection-attributes-available
|
||||
connAttrClientName = "_client_name"
|
||||
connAttrClientNameValue = "Go-MySQL-Driver"
|
||||
connAttrOS = "_os"
|
||||
connAttrOSValue = runtime.GOOS
|
||||
connAttrPlatform = "_platform"
|
||||
connAttrPlatformValue = runtime.GOARCH
|
||||
connAttrPid = "_pid"
|
||||
connAttrServerHost = "_server_host"
|
||||
)
|
||||
|
||||
// MySQL constants documentation:
|
||||
|
|
|
|||
27
vendor/github.com/go-sql-driver/mysql/driver.go
generated
vendored
27
vendor/github.com/go-sql-driver/mysql/driver.go
generated
vendored
|
|
@ -55,6 +55,15 @@ func RegisterDialContext(net string, dial DialContextFunc) {
|
|||
dials[net] = dial
|
||||
}
|
||||
|
||||
// DeregisterDialContext removes the custom dial function registered with the given net.
|
||||
func DeregisterDialContext(net string) {
|
||||
dialsLock.Lock()
|
||||
defer dialsLock.Unlock()
|
||||
if dials != nil {
|
||||
delete(dials, net)
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
|
@ -74,14 +83,18 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &connector{
|
||||
cfg: cfg,
|
||||
}
|
||||
c := newConnector(cfg)
|
||||
return c.Connect(context.Background())
|
||||
}
|
||||
|
||||
// This variable can be replaced with -ldflags like below:
|
||||
// go build "-ldflags=-X github.com/go-sql-driver/mysql.driverName=custom"
|
||||
var driverName = "mysql"
|
||||
|
||||
func init() {
|
||||
sql.Register("mysql", &MySQLDriver{})
|
||||
if driverName != "" {
|
||||
sql.Register(driverName, &MySQLDriver{})
|
||||
}
|
||||
}
|
||||
|
||||
// NewConnector returns new driver.Connector.
|
||||
|
|
@ -92,7 +105,7 @@ func NewConnector(cfg *Config) (driver.Connector, error) {
|
|||
if err := cfg.normalize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &connector{cfg: cfg}, nil
|
||||
return newConnector(cfg), nil
|
||||
}
|
||||
|
||||
// OpenConnector implements driver.DriverContext.
|
||||
|
|
@ -101,7 +114,5 @@ func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &connector{
|
||||
cfg: cfg,
|
||||
}, nil
|
||||
return newConnector(cfg), nil
|
||||
}
|
||||
|
|
|
|||
128
vendor/github.com/go-sql-driver/mysql/dsn.go
generated
vendored
128
vendor/github.com/go-sql-driver/mysql/dsn.go
generated
vendored
|
|
@ -10,6 +10,7 @@ package mysql
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
|
|
@ -34,22 +35,27 @@ var (
|
|||
// 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
|
||||
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, its priority is higher than TLSConfig
|
||||
Timeout time.Duration // Dial timeout
|
||||
ReadTimeout time.Duration // I/O read timeout
|
||||
WriteTimeout time.Duration // I/O write timeout
|
||||
// non boolean fields
|
||||
|
||||
User string // Username
|
||||
Passwd string // Password (requires User)
|
||||
Net string // Network (e.g. "tcp", "tcp6", "unix". default: "tcp")
|
||||
Addr string // Address (default: "127.0.0.1:3306" for "tcp" and "/tmp/mysql.sock" for "unix")
|
||||
DBName string // Database name
|
||||
Params map[string]string // Connection parameters
|
||||
ConnectionAttributes string // Connection Attributes, comma-delimited string of user-defined "key:value" pairs
|
||||
Collation string // Connection collation
|
||||
Loc *time.Location // Location for time.Time values
|
||||
MaxAllowedPacket int // Max packet size allowed
|
||||
ServerPubKey string // Server public key name
|
||||
TLSConfig string // TLS configuration name
|
||||
TLS *tls.Config // TLS configuration, its priority is higher than TLSConfig
|
||||
Timeout time.Duration // Dial timeout
|
||||
ReadTimeout time.Duration // I/O read timeout
|
||||
WriteTimeout time.Duration // I/O write timeout
|
||||
Logger Logger // Logger
|
||||
|
||||
// boolean fields
|
||||
|
||||
AllowAllFiles bool // Allow all files to be used with LOAD DATA LOCAL INFILE
|
||||
AllowCleartextPasswords bool // Allows the cleartext client side plugin
|
||||
|
|
@ -63,17 +69,57 @@ type Config struct {
|
|||
MultiStatements bool // Allow multiple statements in one query
|
||||
ParseTime bool // Parse time values to time.Time
|
||||
RejectReadOnly bool // Reject read-only connections
|
||||
|
||||
// unexported fields. new options should be come here
|
||||
|
||||
beforeConnect func(context.Context, *Config) error // Invoked before a connection is established
|
||||
pubKey *rsa.PublicKey // Server public key
|
||||
timeTruncate time.Duration // Truncate time.Time values to the specified duration
|
||||
}
|
||||
|
||||
// Functional Options Pattern
|
||||
// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
|
||||
type Option func(*Config) error
|
||||
|
||||
// NewConfig creates a new Config and sets default values.
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
Collation: defaultCollation,
|
||||
cfg := &Config{
|
||||
Loc: time.UTC,
|
||||
MaxAllowedPacket: defaultMaxAllowedPacket,
|
||||
Logger: defaultLogger,
|
||||
AllowNativePasswords: true,
|
||||
CheckConnLiveness: true,
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Apply applies the given options to the Config object.
|
||||
func (c *Config) Apply(opts ...Option) error {
|
||||
for _, opt := range opts {
|
||||
err := opt(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TimeTruncate sets the time duration to truncate time.Time values in
|
||||
// query parameters.
|
||||
func TimeTruncate(d time.Duration) Option {
|
||||
return func(cfg *Config) error {
|
||||
cfg.timeTruncate = d
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// BeforeConnect sets the function to be invoked before a connection is established.
|
||||
func BeforeConnect(fn func(context.Context, *Config) error) Option {
|
||||
return func(cfg *Config) error {
|
||||
cfg.beforeConnect = fn
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg *Config) Clone() *Config {
|
||||
|
|
@ -97,7 +143,7 @@ func (cfg *Config) Clone() *Config {
|
|||
}
|
||||
|
||||
func (cfg *Config) normalize() error {
|
||||
if cfg.InterpolateParams && unsafeCollations[cfg.Collation] {
|
||||
if cfg.InterpolateParams && cfg.Collation != "" && unsafeCollations[cfg.Collation] {
|
||||
return errInvalidDSNUnsafeCollation
|
||||
}
|
||||
|
||||
|
|
@ -153,6 +199,10 @@ func (cfg *Config) normalize() error {
|
|||
}
|
||||
}
|
||||
|
||||
if cfg.Logger == nil {
|
||||
cfg.Logger = defaultLogger
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +221,8 @@ func writeDSNParam(buf *bytes.Buffer, hasParam *bool, name, value string) {
|
|||
|
||||
// FormatDSN formats the given Config into a DSN string which can be passed to
|
||||
// the driver.
|
||||
//
|
||||
// Note: use [NewConnector] and [database/sql.OpenDB] to open a connection from a [*Config].
|
||||
func (cfg *Config) FormatDSN() string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
|
|
@ -196,7 +248,7 @@ func (cfg *Config) FormatDSN() string {
|
|||
|
||||
// /dbname
|
||||
buf.WriteByte('/')
|
||||
buf.WriteString(cfg.DBName)
|
||||
buf.WriteString(url.PathEscape(cfg.DBName))
|
||||
|
||||
// [?param1=value1&...¶mN=valueN]
|
||||
hasParam := false
|
||||
|
|
@ -230,7 +282,7 @@ func (cfg *Config) FormatDSN() string {
|
|||
writeDSNParam(&buf, &hasParam, "clientFoundRows", "true")
|
||||
}
|
||||
|
||||
if col := cfg.Collation; col != defaultCollation && len(col) > 0 {
|
||||
if col := cfg.Collation; col != "" {
|
||||
writeDSNParam(&buf, &hasParam, "collation", col)
|
||||
}
|
||||
|
||||
|
|
@ -254,6 +306,10 @@ func (cfg *Config) FormatDSN() string {
|
|||
writeDSNParam(&buf, &hasParam, "parseTime", "true")
|
||||
}
|
||||
|
||||
if cfg.timeTruncate > 0 {
|
||||
writeDSNParam(&buf, &hasParam, "timeTruncate", cfg.timeTruncate.String())
|
||||
}
|
||||
|
||||
if cfg.ReadTimeout > 0 {
|
||||
writeDSNParam(&buf, &hasParam, "readTimeout", cfg.ReadTimeout.String())
|
||||
}
|
||||
|
|
@ -358,7 +414,11 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
|
|||
break
|
||||
}
|
||||
}
|
||||
cfg.DBName = dsn[i+1 : j]
|
||||
|
||||
dbname := dsn[i+1 : j]
|
||||
if cfg.DBName, err = url.PathUnescape(dbname); err != nil {
|
||||
return nil, fmt.Errorf("invalid dbname %q: %w", dbname, err)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
|
@ -378,13 +438,13 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
|
|||
// Values must be url.QueryEscape'ed
|
||||
func parseDSNParams(cfg *Config, params string) (err error) {
|
||||
for _, v := range strings.Split(params, "&") {
|
||||
param := strings.SplitN(v, "=", 2)
|
||||
if len(param) != 2 {
|
||||
key, value, found := strings.Cut(v, "=")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
|
||||
// cfg params
|
||||
switch value := param[1]; param[0] {
|
||||
switch key {
|
||||
// Disable INFILE allowlist / enable all files
|
||||
case "allowAllFiles":
|
||||
var isBool bool
|
||||
|
|
@ -490,6 +550,13 @@ func parseDSNParams(cfg *Config, params string) (err error) {
|
|||
return errors.New("invalid bool value: " + value)
|
||||
}
|
||||
|
||||
// time.Time truncation
|
||||
case "timeTruncate":
|
||||
cfg.timeTruncate, err = time.ParseDuration(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid timeTruncate value: %v, error: %w", value, err)
|
||||
}
|
||||
|
||||
// I/O read Timeout
|
||||
case "readTimeout":
|
||||
cfg.ReadTimeout, err = time.ParseDuration(value)
|
||||
|
|
@ -554,13 +621,22 @@ func parseDSNParams(cfg *Config, params string) (err error) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Connection attributes
|
||||
case "connectionAttributes":
|
||||
connectionAttributes, err := url.QueryUnescape(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid connectionAttributes value: %v", err)
|
||||
}
|
||||
cfg.ConnectionAttributes = connectionAttributes
|
||||
|
||||
default:
|
||||
// lazy init
|
||||
if cfg.Params == nil {
|
||||
cfg.Params = make(map[string]string)
|
||||
}
|
||||
|
||||
if cfg.Params[param[0]], err = url.QueryUnescape(value); err != nil {
|
||||
if cfg.Params[key], err = url.QueryUnescape(value); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
vendor/github.com/go-sql-driver/mysql/errors.go
generated
vendored
16
vendor/github.com/go-sql-driver/mysql/errors.go
generated
vendored
|
|
@ -21,7 +21,7 @@ var (
|
|||
ErrMalformPkt = errors.New("malformed packet")
|
||||
ErrNoTLS = errors.New("TLS requested but server does not support TLS")
|
||||
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.")
|
||||
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+")
|
||||
|
|
@ -37,20 +37,26 @@ var (
|
|||
errBadConnNoWrite = errors.New("bad connection")
|
||||
)
|
||||
|
||||
var errLog = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile))
|
||||
var defaultLogger = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime|log.Lshortfile))
|
||||
|
||||
// Logger is used to log critical error messages.
|
||||
type Logger interface {
|
||||
Print(v ...interface{})
|
||||
Print(v ...any)
|
||||
}
|
||||
|
||||
// SetLogger is used to set the logger for critical errors.
|
||||
// NopLogger is a nop implementation of the Logger interface.
|
||||
type NopLogger struct{}
|
||||
|
||||
// Print implements Logger interface.
|
||||
func (nl *NopLogger) Print(_ ...any) {}
|
||||
|
||||
// SetLogger is used to set the default logger for critical errors.
|
||||
// The initial logger is os.Stderr.
|
||||
func SetLogger(logger Logger) error {
|
||||
if logger == nil {
|
||||
return errors.New("logger is nil")
|
||||
}
|
||||
errLog = logger
|
||||
defaultLogger = logger
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
70
vendor/github.com/go-sql-driver/mysql/fields.go
generated
vendored
70
vendor/github.com/go-sql-driver/mysql/fields.go
generated
vendored
|
|
@ -18,7 +18,7 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
case fieldTypeBit:
|
||||
return "BIT"
|
||||
case fieldTypeBLOB:
|
||||
if mf.charSet != collations[binaryCollation] {
|
||||
if mf.charSet != binaryCollationID {
|
||||
return "TEXT"
|
||||
}
|
||||
return "BLOB"
|
||||
|
|
@ -37,6 +37,9 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
case fieldTypeGeometry:
|
||||
return "GEOMETRY"
|
||||
case fieldTypeInt24:
|
||||
if mf.flags&flagUnsigned != 0 {
|
||||
return "UNSIGNED MEDIUMINT"
|
||||
}
|
||||
return "MEDIUMINT"
|
||||
case fieldTypeJSON:
|
||||
return "JSON"
|
||||
|
|
@ -46,7 +49,7 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
}
|
||||
return "INT"
|
||||
case fieldTypeLongBLOB:
|
||||
if mf.charSet != collations[binaryCollation] {
|
||||
if mf.charSet != binaryCollationID {
|
||||
return "LONGTEXT"
|
||||
}
|
||||
return "LONGBLOB"
|
||||
|
|
@ -56,7 +59,7 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
}
|
||||
return "BIGINT"
|
||||
case fieldTypeMediumBLOB:
|
||||
if mf.charSet != collations[binaryCollation] {
|
||||
if mf.charSet != binaryCollationID {
|
||||
return "MEDIUMTEXT"
|
||||
}
|
||||
return "MEDIUMBLOB"
|
||||
|
|
@ -74,7 +77,12 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
}
|
||||
return "SMALLINT"
|
||||
case fieldTypeString:
|
||||
if mf.charSet == collations[binaryCollation] {
|
||||
if mf.flags&flagEnum != 0 {
|
||||
return "ENUM"
|
||||
} else if mf.flags&flagSet != 0 {
|
||||
return "SET"
|
||||
}
|
||||
if mf.charSet == binaryCollationID {
|
||||
return "BINARY"
|
||||
}
|
||||
return "CHAR"
|
||||
|
|
@ -88,17 +96,17 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
}
|
||||
return "TINYINT"
|
||||
case fieldTypeTinyBLOB:
|
||||
if mf.charSet != collations[binaryCollation] {
|
||||
if mf.charSet != binaryCollationID {
|
||||
return "TINYTEXT"
|
||||
}
|
||||
return "TINYBLOB"
|
||||
case fieldTypeVarChar:
|
||||
if mf.charSet == collations[binaryCollation] {
|
||||
if mf.charSet == binaryCollationID {
|
||||
return "VARBINARY"
|
||||
}
|
||||
return "VARCHAR"
|
||||
case fieldTypeVarString:
|
||||
if mf.charSet == collations[binaryCollation] {
|
||||
if mf.charSet == binaryCollationID {
|
||||
return "VARBINARY"
|
||||
}
|
||||
return "VARCHAR"
|
||||
|
|
@ -110,21 +118,23 @@ func (mf *mysqlField) typeDatabaseName() string {
|
|||
}
|
||||
|
||||
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(sql.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{}))
|
||||
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(sql.NullTime{})
|
||||
scanTypeUint8 = reflect.TypeOf(uint8(0))
|
||||
scanTypeUint16 = reflect.TypeOf(uint16(0))
|
||||
scanTypeUint32 = reflect.TypeOf(uint32(0))
|
||||
scanTypeUint64 = reflect.TypeOf(uint64(0))
|
||||
scanTypeString = reflect.TypeOf("")
|
||||
scanTypeNullString = reflect.TypeOf(sql.NullString{})
|
||||
scanTypeBytes = reflect.TypeOf([]byte{})
|
||||
scanTypeUnknown = reflect.TypeOf(new(any))
|
||||
)
|
||||
|
||||
type mysqlField struct {
|
||||
|
|
@ -187,12 +197,18 @@ func (mf *mysqlField) scanType() reflect.Type {
|
|||
}
|
||||
return scanTypeNullFloat
|
||||
|
||||
case fieldTypeBit, fieldTypeTinyBLOB, fieldTypeMediumBLOB, fieldTypeLongBLOB,
|
||||
fieldTypeBLOB, fieldTypeVarString, fieldTypeString, fieldTypeGeometry:
|
||||
if mf.charSet == binaryCollationID {
|
||||
return scanTypeBytes
|
||||
}
|
||||
fallthrough
|
||||
case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar,
|
||||
fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB,
|
||||
fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB,
|
||||
fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON,
|
||||
fieldTypeTime:
|
||||
return scanTypeRawBytes
|
||||
fieldTypeEnum, fieldTypeSet, fieldTypeJSON, fieldTypeTime:
|
||||
if mf.flags&flagNotNULL != 0 {
|
||||
return scanTypeString
|
||||
}
|
||||
return scanTypeNullString
|
||||
|
||||
case fieldTypeDate, fieldTypeNewDate,
|
||||
fieldTypeTimestamp, fieldTypeDateTime:
|
||||
|
|
|
|||
25
vendor/github.com/go-sql-driver/mysql/fuzz.go
generated
vendored
25
vendor/github.com/go-sql-driver/mysql/fuzz.go
generated
vendored
|
|
@ -1,25 +0,0 @@
|
|||
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package.
|
||||
//
|
||||
// Copyright 2020 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/.
|
||||
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package mysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
db, err := sql.Open("mysql", string(data))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
db.Close()
|
||||
return 1
|
||||
}
|
||||
12
vendor/github.com/go-sql-driver/mysql/infile.go
generated
vendored
12
vendor/github.com/go-sql-driver/mysql/infile.go
generated
vendored
|
|
@ -93,7 +93,7 @@ func deferredClose(err *error, closer io.Closer) {
|
|||
|
||||
const defaultPacketSize = 16 * 1024 // 16KB is small enough for disk readahead and large enough for TCP
|
||||
|
||||
func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
|
||||
func (mc *okHandler) handleInFileRequest(name string) (err error) {
|
||||
var rdr io.Reader
|
||||
var data []byte
|
||||
packetSize := defaultPacketSize
|
||||
|
|
@ -116,10 +116,10 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
|
|||
defer deferredClose(&err, cl)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("Reader '%s' is <nil>", name)
|
||||
err = fmt.Errorf("reader '%s' is <nil>", name)
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("Reader '%s' is not registered", name)
|
||||
err = fmt.Errorf("reader '%s' is not registered", name)
|
||||
}
|
||||
} else { // File
|
||||
name = strings.Trim(name, `"`)
|
||||
|
|
@ -154,7 +154,7 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
|
|||
for err == nil {
|
||||
n, err = rdr.Read(data[4:])
|
||||
if n > 0 {
|
||||
if ioErr := mc.writePacket(data[:4+n]); ioErr != nil {
|
||||
if ioErr := mc.conn().writePacket(data[:4+n]); ioErr != nil {
|
||||
return ioErr
|
||||
}
|
||||
}
|
||||
|
|
@ -168,7 +168,7 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
|
|||
if data == nil {
|
||||
data = make([]byte, 4)
|
||||
}
|
||||
if ioErr := mc.writePacket(data[:4]); ioErr != nil {
|
||||
if ioErr := mc.conn().writePacket(data[:4]); ioErr != nil {
|
||||
return ioErr
|
||||
}
|
||||
|
||||
|
|
@ -177,6 +177,6 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
|
|||
return mc.readResultOK()
|
||||
}
|
||||
|
||||
mc.readPacket()
|
||||
mc.conn().readPacket()
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/go-sql-driver/mysql/nulltime.go
generated
vendored
4
vendor/github.com/go-sql-driver/mysql/nulltime.go
generated
vendored
|
|
@ -38,7 +38,7 @@ type NullTime sql.NullTime
|
|||
// Scan implements the Scanner interface.
|
||||
// The value type must be time.Time or string / []byte (formatted time-string),
|
||||
// otherwise Scan fails.
|
||||
func (nt *NullTime) Scan(value interface{}) (err error) {
|
||||
func (nt *NullTime) Scan(value any) (err error) {
|
||||
if value == nil {
|
||||
nt.Time, nt.Valid = time.Time{}, false
|
||||
return
|
||||
|
|
@ -59,7 +59,7 @@ func (nt *NullTime) Scan(value interface{}) (err error) {
|
|||
}
|
||||
|
||||
nt.Valid = false
|
||||
return fmt.Errorf("Can't convert %T to time.Time", value)
|
||||
return fmt.Errorf("can't convert %T to time.Time", value)
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
|
|
|
|||
209
vendor/github.com/go-sql-driver/mysql/packets.go
generated
vendored
209
vendor/github.com/go-sql-driver/mysql/packets.go
generated
vendored
|
|
@ -14,10 +14,10 @@ import (
|
|||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
|
|||
if cerr := mc.canceled.Value(); cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
mc.Close()
|
||||
return nil, ErrInvalidConn
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
|
|||
|
||||
// check packet sync [8 bit]
|
||||
if data[3] != mc.sequence {
|
||||
mc.Close()
|
||||
if data[3] > mc.sequence {
|
||||
return nil, ErrPktSyncMul
|
||||
}
|
||||
|
|
@ -56,7 +57,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
|
|||
if pktLen == 0 {
|
||||
// there was no previous packet
|
||||
if prevData == nil {
|
||||
errLog.Print(ErrMalformPkt)
|
||||
mc.log(ErrMalformPkt)
|
||||
mc.Close()
|
||||
return nil, ErrInvalidConn
|
||||
}
|
||||
|
|
@ -70,7 +71,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
|
|||
if cerr := mc.canceled.Value(); cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
mc.Close()
|
||||
return nil, ErrInvalidConn
|
||||
}
|
||||
|
|
@ -97,34 +98,6 @@ func (mc *mysqlConn) writePacket(data []byte) error {
|
|||
return ErrPktTooLarge
|
||||
}
|
||||
|
||||
// Perform a stale connection check. We only perform this check for
|
||||
// the first query on a connection that has been checked out of the
|
||||
// connection pool: a fresh connection from the pool is more likely
|
||||
// to be stale, and it has not performed any previous writes that
|
||||
// could cause data corruption, so it's safe to return ErrBadConn
|
||||
// if the check fails.
|
||||
if mc.reset {
|
||||
mc.reset = false
|
||||
conn := mc.netConn
|
||||
if mc.rawConn != nil {
|
||||
conn = mc.rawConn
|
||||
}
|
||||
var err error
|
||||
if mc.cfg.CheckConnLiveness {
|
||||
if mc.cfg.ReadTimeout != 0 {
|
||||
err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout))
|
||||
}
|
||||
if err == nil {
|
||||
err = connCheck(conn)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
errLog.Print("closing bad idle connection: ", err)
|
||||
mc.Close()
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
var size int
|
||||
if pktLen >= maxPacketSize {
|
||||
|
|
@ -161,7 +134,7 @@ func (mc *mysqlConn) writePacket(data []byte) error {
|
|||
// Handle error
|
||||
if err == nil { // n != len(data)
|
||||
mc.cleanup()
|
||||
errLog.Print(ErrMalformPkt)
|
||||
mc.log(ErrMalformPkt)
|
||||
} else {
|
||||
if cerr := mc.canceled.Value(); cerr != nil {
|
||||
return cerr
|
||||
|
|
@ -171,7 +144,7 @@ func (mc *mysqlConn) writePacket(data []byte) error {
|
|||
return errBadConnNoWrite
|
||||
}
|
||||
mc.cleanup()
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
}
|
||||
return ErrInvalidConn
|
||||
}
|
||||
|
|
@ -239,7 +212,7 @@ func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err erro
|
|||
// reserved (all [00]) [10 bytes]
|
||||
pos += 1 + 2 + 2 + 1 + 10
|
||||
|
||||
// second part of the password cipher [mininum 13 bytes],
|
||||
// second part of the password cipher [minimum 13 bytes],
|
||||
// where len=MAX(13, length of auth-plugin-data - 8)
|
||||
//
|
||||
// The web documentation is ambiguous about the length. However,
|
||||
|
|
@ -285,6 +258,7 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
|
|||
clientLocalFiles |
|
||||
clientPluginAuth |
|
||||
clientMultiResults |
|
||||
clientConnectAttrs |
|
||||
mc.flags&clientLongFlag
|
||||
|
||||
if mc.cfg.ClientFoundRows {
|
||||
|
|
@ -318,11 +292,17 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
|
|||
pktLen += n + 1
|
||||
}
|
||||
|
||||
// encode length of the connection attributes
|
||||
var connAttrsLEIBuf [9]byte
|
||||
connAttrsLen := len(mc.connector.encodedAttributes)
|
||||
connAttrsLEI := appendLengthEncodedInteger(connAttrsLEIBuf[:0], uint64(connAttrsLen))
|
||||
pktLen += len(connAttrsLEI) + len(mc.connector.encodedAttributes)
|
||||
|
||||
// Calculate packet length and get buffer with that size
|
||||
data, err := mc.buf.takeSmallBuffer(pktLen + 4)
|
||||
data, err := mc.buf.takeBuffer(pktLen + 4)
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -338,14 +318,18 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
|
|||
data[10] = 0x00
|
||||
data[11] = 0x00
|
||||
|
||||
// Charset [1 byte]
|
||||
// Collation ID [1 byte]
|
||||
cname := mc.cfg.Collation
|
||||
if cname == "" {
|
||||
cname = defaultCollation
|
||||
}
|
||||
var found bool
|
||||
data[12], found = collations[mc.cfg.Collation]
|
||||
data[12], found = collations[cname]
|
||||
if !found {
|
||||
// Note possibility for false negatives:
|
||||
// could be triggered although the collation is valid if the
|
||||
// collations map does not contain entries the server supports.
|
||||
return errors.New("unknown collation")
|
||||
return fmt.Errorf("unknown collation: %q", cname)
|
||||
}
|
||||
|
||||
// Filler [23 bytes] (all 0x00)
|
||||
|
|
@ -367,7 +351,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
|
|||
if err := tlsConn.Handshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
mc.rawConn = mc.netConn
|
||||
mc.netConn = tlsConn
|
||||
mc.buf.nc = tlsConn
|
||||
}
|
||||
|
|
@ -394,6 +377,10 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string
|
|||
data[pos] = 0x00
|
||||
pos++
|
||||
|
||||
// Connection Attributes
|
||||
pos += copy(data[pos:], connAttrsLEI)
|
||||
pos += copy(data[pos:], []byte(mc.connector.encodedAttributes))
|
||||
|
||||
// Send Auth packet
|
||||
return mc.writePacket(data[:pos])
|
||||
}
|
||||
|
|
@ -404,7 +391,7 @@ func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
|
|||
data, err := mc.buf.takeSmallBuffer(pktLen)
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -424,7 +411,7 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
|
|||
data, err := mc.buf.takeSmallBuffer(4 + 1)
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +430,7 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
|
|||
data, err := mc.buf.takeBuffer(pktLen + 4)
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +451,7 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
|
|||
data, err := mc.buf.takeSmallBuffer(4 + 1 + 4)
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -495,7 +482,9 @@ func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
|
|||
switch data[0] {
|
||||
|
||||
case iOK:
|
||||
return nil, "", mc.handleOkPacket(data)
|
||||
// resultUnchanged, since auth happens before any queries or
|
||||
// commands have been executed.
|
||||
return nil, "", mc.resultUnchanged().handleOkPacket(data)
|
||||
|
||||
case iAuthMoreData:
|
||||
return data[1:], "", err
|
||||
|
|
@ -518,9 +507,9 @@ func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns error if Packet is not an 'Result OK'-Packet
|
||||
func (mc *mysqlConn) readResultOK() error {
|
||||
data, err := mc.readPacket()
|
||||
// Returns error if Packet is not a 'Result OK'-Packet
|
||||
func (mc *okHandler) readResultOK() error {
|
||||
data, err := mc.conn().readPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -528,13 +517,17 @@ func (mc *mysqlConn) readResultOK() error {
|
|||
if data[0] == iOK {
|
||||
return mc.handleOkPacket(data)
|
||||
}
|
||||
return mc.handleErrorPacket(data)
|
||||
return mc.conn().handleErrorPacket(data)
|
||||
}
|
||||
|
||||
// Result Set Header Packet
|
||||
// http://dev.mysql.com/doc/internals/en/com-query-response.html#packet-ProtocolText::Resultset
|
||||
func (mc *mysqlConn) readResultSetHeaderPacket() (int, error) {
|
||||
data, err := mc.readPacket()
|
||||
func (mc *okHandler) readResultSetHeaderPacket() (int, error) {
|
||||
// handleOkPacket replaces both values; other cases leave the values unchanged.
|
||||
mc.result.affectedRows = append(mc.result.affectedRows, 0)
|
||||
mc.result.insertIds = append(mc.result.insertIds, 0)
|
||||
|
||||
data, err := mc.conn().readPacket()
|
||||
if err == nil {
|
||||
switch data[0] {
|
||||
|
||||
|
|
@ -542,19 +535,16 @@ func (mc *mysqlConn) readResultSetHeaderPacket() (int, error) {
|
|||
return 0, mc.handleOkPacket(data)
|
||||
|
||||
case iERR:
|
||||
return 0, mc.handleErrorPacket(data)
|
||||
return 0, mc.conn().handleErrorPacket(data)
|
||||
|
||||
case iLocalInFile:
|
||||
return 0, mc.handleInFileRequest(string(data[1:]))
|
||||
}
|
||||
|
||||
// column count
|
||||
num, _, n := readLengthEncodedInteger(data)
|
||||
if n-len(data) == 0 {
|
||||
return int(num), nil
|
||||
}
|
||||
|
||||
return 0, ErrMalformPkt
|
||||
num, _, _ := readLengthEncodedInteger(data)
|
||||
// ignore remaining data in the packet. see #1478.
|
||||
return int(num), nil
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -607,18 +597,61 @@ func readStatus(b []byte) statusFlag {
|
|||
return statusFlag(b[0]) | statusFlag(b[1])<<8
|
||||
}
|
||||
|
||||
// Returns an instance of okHandler for codepaths where mysqlConn.result doesn't
|
||||
// need to be cleared first (e.g. during authentication, or while additional
|
||||
// resultsets are being fetched.)
|
||||
func (mc *mysqlConn) resultUnchanged() *okHandler {
|
||||
return (*okHandler)(mc)
|
||||
}
|
||||
|
||||
// okHandler represents the state of the connection when mysqlConn.result has
|
||||
// been prepared for processing of OK packets.
|
||||
//
|
||||
// To correctly populate mysqlConn.result (updated by handleOkPacket()), all
|
||||
// callpaths must either:
|
||||
//
|
||||
// 1. first clear it using clearResult(), or
|
||||
// 2. confirm that they don't need to (by calling resultUnchanged()).
|
||||
//
|
||||
// Both return an instance of type *okHandler.
|
||||
type okHandler mysqlConn
|
||||
|
||||
// Exposes the underlying type's methods.
|
||||
func (mc *okHandler) conn() *mysqlConn {
|
||||
return (*mysqlConn)(mc)
|
||||
}
|
||||
|
||||
// clearResult clears the connection's stored affectedRows and insertIds
|
||||
// fields.
|
||||
//
|
||||
// It returns a handler that can process OK responses.
|
||||
func (mc *mysqlConn) clearResult() *okHandler {
|
||||
mc.result = mysqlResult{}
|
||||
return (*okHandler)(mc)
|
||||
}
|
||||
|
||||
// Ok Packet
|
||||
// http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-OK_Packet
|
||||
func (mc *mysqlConn) handleOkPacket(data []byte) error {
|
||||
func (mc *okHandler) handleOkPacket(data []byte) error {
|
||||
var n, m int
|
||||
var affectedRows, insertId uint64
|
||||
|
||||
// 0x00 [1 byte]
|
||||
|
||||
// Affected rows [Length Coded Binary]
|
||||
mc.affectedRows, _, n = readLengthEncodedInteger(data[1:])
|
||||
affectedRows, _, n = readLengthEncodedInteger(data[1:])
|
||||
|
||||
// Insert id [Length Coded Binary]
|
||||
mc.insertId, _, m = readLengthEncodedInteger(data[1+n:])
|
||||
insertId, _, m = readLengthEncodedInteger(data[1+n:])
|
||||
|
||||
// Update for the current statement result (only used by
|
||||
// readResultSetHeaderPacket).
|
||||
if len(mc.result.affectedRows) > 0 {
|
||||
mc.result.affectedRows[len(mc.result.affectedRows)-1] = int64(affectedRows)
|
||||
}
|
||||
if len(mc.result.insertIds) > 0 {
|
||||
mc.result.insertIds[len(mc.result.insertIds)-1] = int64(insertId)
|
||||
}
|
||||
|
||||
// server_status [2 bytes]
|
||||
mc.status = readStatus(data[1+n+m : 1+n+m+2])
|
||||
|
|
@ -769,7 +802,8 @@ func (rows *textRows) readRow(dest []driver.Value) error {
|
|||
|
||||
for i := range dest {
|
||||
// Read bytes and convert to string
|
||||
dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
|
||||
var buf []byte
|
||||
buf, isNull, n, err = readLengthEncodedString(data[pos:])
|
||||
pos += n
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -781,19 +815,40 @@ func (rows *textRows) readRow(dest []driver.Value) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if !mc.parseTime {
|
||||
continue
|
||||
}
|
||||
|
||||
// Parse time field
|
||||
switch rows.rs.columns[i].fieldType {
|
||||
case fieldTypeTimestamp,
|
||||
fieldTypeDateTime,
|
||||
fieldTypeDate,
|
||||
fieldTypeNewDate:
|
||||
if dest[i], err = parseDateTime(dest[i].([]byte), mc.cfg.Loc); err != nil {
|
||||
return err
|
||||
if mc.parseTime {
|
||||
dest[i], err = parseDateTime(buf, mc.cfg.Loc)
|
||||
} else {
|
||||
dest[i] = buf
|
||||
}
|
||||
|
||||
case fieldTypeTiny, fieldTypeShort, fieldTypeInt24, fieldTypeYear, fieldTypeLong:
|
||||
dest[i], err = strconv.ParseInt(string(buf), 10, 64)
|
||||
|
||||
case fieldTypeLongLong:
|
||||
if rows.rs.columns[i].flags&flagUnsigned != 0 {
|
||||
dest[i], err = strconv.ParseUint(string(buf), 10, 64)
|
||||
} else {
|
||||
dest[i], err = strconv.ParseInt(string(buf), 10, 64)
|
||||
}
|
||||
|
||||
case fieldTypeFloat:
|
||||
var d float64
|
||||
d, err = strconv.ParseFloat(string(buf), 32)
|
||||
dest[i] = float32(d)
|
||||
|
||||
case fieldTypeDouble:
|
||||
dest[i], err = strconv.ParseFloat(string(buf), 64)
|
||||
|
||||
default:
|
||||
dest[i] = buf
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -938,7 +993,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
|
|||
}
|
||||
if err != nil {
|
||||
// cannot take the buffer. Something must be wrong with the connection
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
|
||||
|
|
@ -1116,7 +1171,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
|
|||
if v.IsZero() {
|
||||
b = append(b, "0000-00-00"...)
|
||||
} else {
|
||||
b, err = appendDateTime(b, v.In(mc.cfg.Loc))
|
||||
b, err = appendDateTime(b, v.In(mc.cfg.Loc), mc.cfg.timeTruncate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1137,7 +1192,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
|
|||
if valuesCap != cap(paramValues) {
|
||||
data = append(data[:pos], paramValues...)
|
||||
if err = mc.buf.store(data); err != nil {
|
||||
errLog.Print(err)
|
||||
mc.log(err)
|
||||
return errBadConnNoWrite
|
||||
}
|
||||
}
|
||||
|
|
@ -1149,7 +1204,9 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
|
|||
return mc.writePacket(data)
|
||||
}
|
||||
|
||||
func (mc *mysqlConn) discardResults() error {
|
||||
// For each remaining resultset in the stream, discards its rows and updates
|
||||
// mc.affectedRows and mc.insertIds.
|
||||
func (mc *okHandler) discardResults() error {
|
||||
for mc.status&statusMoreResultsExists != 0 {
|
||||
resLen, err := mc.readResultSetHeaderPacket()
|
||||
if err != nil {
|
||||
|
|
@ -1157,11 +1214,11 @@ func (mc *mysqlConn) discardResults() error {
|
|||
}
|
||||
if resLen > 0 {
|
||||
// columns
|
||||
if err := mc.readUntilEOF(); err != nil {
|
||||
if err := mc.conn().readUntilEOF(); err != nil {
|
||||
return err
|
||||
}
|
||||
// rows
|
||||
if err := mc.readUntilEOF(); err != nil {
|
||||
if err := mc.conn().readUntilEOF(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
vendor/github.com/go-sql-driver/mysql/result.go
generated
vendored
36
vendor/github.com/go-sql-driver/mysql/result.go
generated
vendored
|
|
@ -8,15 +8,43 @@
|
|||
|
||||
package mysql
|
||||
|
||||
import "database/sql/driver"
|
||||
|
||||
// Result exposes data not available through *connection.Result.
|
||||
//
|
||||
// This is accessible by executing statements using sql.Conn.Raw() and
|
||||
// downcasting the returned result:
|
||||
//
|
||||
// res, err := rawConn.Exec(...)
|
||||
// res.(mysql.Result).AllRowsAffected()
|
||||
type Result interface {
|
||||
driver.Result
|
||||
// AllRowsAffected returns a slice containing the affected rows for each
|
||||
// executed statement.
|
||||
AllRowsAffected() []int64
|
||||
// AllLastInsertIds returns a slice containing the last inserted ID for each
|
||||
// executed statement.
|
||||
AllLastInsertIds() []int64
|
||||
}
|
||||
|
||||
type mysqlResult struct {
|
||||
affectedRows int64
|
||||
insertId int64
|
||||
// One entry in both slices is created for every executed statement result.
|
||||
affectedRows []int64
|
||||
insertIds []int64
|
||||
}
|
||||
|
||||
func (res *mysqlResult) LastInsertId() (int64, error) {
|
||||
return res.insertId, nil
|
||||
return res.insertIds[len(res.insertIds)-1], nil
|
||||
}
|
||||
|
||||
func (res *mysqlResult) RowsAffected() (int64, error) {
|
||||
return res.affectedRows, nil
|
||||
return res.affectedRows[len(res.affectedRows)-1], nil
|
||||
}
|
||||
|
||||
func (res *mysqlResult) AllLastInsertIds() []int64 {
|
||||
return append([]int64{}, res.insertIds...) // defensive copy
|
||||
}
|
||||
|
||||
func (res *mysqlResult) AllRowsAffected() []int64 {
|
||||
return append([]int64{}, res.affectedRows...) // defensive copy
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/go-sql-driver/mysql/rows.go
generated
vendored
13
vendor/github.com/go-sql-driver/mysql/rows.go
generated
vendored
|
|
@ -123,7 +123,8 @@ func (rows *mysqlRows) Close() (err error) {
|
|||
err = mc.readUntilEOF()
|
||||
}
|
||||
if err == nil {
|
||||
if err = mc.discardResults(); err != nil {
|
||||
handleOk := mc.clearResult()
|
||||
if err = handleOk.discardResults(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -160,7 +161,15 @@ func (rows *mysqlRows) nextResultSet() (int, error) {
|
|||
return 0, io.EOF
|
||||
}
|
||||
rows.rs = resultSet{}
|
||||
return rows.mc.readResultSetHeaderPacket()
|
||||
// rows.mc.affectedRows and rows.mc.insertIds accumulate on each call to
|
||||
// nextResultSet.
|
||||
resLen, err := rows.mc.resultUnchanged().readResultSetHeaderPacket()
|
||||
if err != nil {
|
||||
// Clean up about multi-results flag
|
||||
rows.rs.done = true
|
||||
rows.mc.status = rows.mc.status & (^statusMoreResultsExists)
|
||||
}
|
||||
return resLen, err
|
||||
}
|
||||
|
||||
func (rows *mysqlRows) nextNotEmptyResultSet() (int, error) {
|
||||
|
|
|
|||
23
vendor/github.com/go-sql-driver/mysql/statement.go
generated
vendored
23
vendor/github.com/go-sql-driver/mysql/statement.go
generated
vendored
|
|
@ -51,7 +51,7 @@ func (stmt *mysqlStmt) CheckNamedValue(nv *driver.NamedValue) (err error) {
|
|||
|
||||
func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
|
||||
if stmt.mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
stmt.mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
// Send command
|
||||
|
|
@ -61,12 +61,10 @@ func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
|
|||
}
|
||||
|
||||
mc := stmt.mc
|
||||
|
||||
mc.affectedRows = 0
|
||||
mc.insertId = 0
|
||||
handleOk := stmt.mc.clearResult()
|
||||
|
||||
// Read Result
|
||||
resLen, err := mc.readResultSetHeaderPacket()
|
||||
resLen, err := handleOk.readResultSetHeaderPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -83,14 +81,12 @@ func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if err := mc.discardResults(); err != nil {
|
||||
if err := handleOk.discardResults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &mysqlResult{
|
||||
affectedRows: int64(mc.affectedRows),
|
||||
insertId: int64(mc.insertId),
|
||||
}, nil
|
||||
copied := mc.result
|
||||
return &copied, nil
|
||||
}
|
||||
|
||||
func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
|
||||
|
|
@ -99,7 +95,7 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
|
|||
|
||||
func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
|
||||
if stmt.mc.closed.Load() {
|
||||
errLog.Print(ErrInvalidConn)
|
||||
stmt.mc.log(ErrInvalidConn)
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
// Send command
|
||||
|
|
@ -111,7 +107,8 @@ func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
|
|||
mc := stmt.mc
|
||||
|
||||
// Read Result
|
||||
resLen, err := mc.readResultSetHeaderPacket()
|
||||
handleOk := stmt.mc.clearResult()
|
||||
resLen, err := handleOk.readResultSetHeaderPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -144,7 +141,7 @@ type converter struct{}
|
|||
// 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) {
|
||||
func (c converter) ConvertValue(v any) (driver.Value, error) {
|
||||
if driver.IsValue(v) {
|
||||
return v, nil
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/go-sql-driver/mysql/utils.go
generated
vendored
13
vendor/github.com/go-sql-driver/mysql/utils.go
generated
vendored
|
|
@ -36,7 +36,7 @@ var (
|
|||
// registering it.
|
||||
//
|
||||
// rootCertPool := x509.NewCertPool()
|
||||
// pem, err := ioutil.ReadFile("/path/ca-cert.pem")
|
||||
// pem, err := os.ReadFile("/path/ca-cert.pem")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
|
|
@ -265,7 +265,11 @@ func parseBinaryDateTime(num uint64, data []byte, loc *time.Location) (driver.Va
|
|||
return nil, fmt.Errorf("invalid DATETIME packet length %d", num)
|
||||
}
|
||||
|
||||
func appendDateTime(buf []byte, t time.Time) ([]byte, error) {
|
||||
func appendDateTime(buf []byte, t time.Time, timeTruncate time.Duration) ([]byte, error) {
|
||||
if timeTruncate > 0 {
|
||||
t = t.Truncate(timeTruncate)
|
||||
}
|
||||
|
||||
year, month, day := t.Date()
|
||||
hour, min, sec := t.Clock()
|
||||
nsec := t.Nanosecond()
|
||||
|
|
@ -616,6 +620,11 @@ func appendLengthEncodedInteger(b []byte, n uint64) []byte {
|
|||
byte(n>>32), byte(n>>40), byte(n>>48), byte(n>>56))
|
||||
}
|
||||
|
||||
func appendLengthEncodedString(b []byte, s string) []byte {
|
||||
b = appendLengthEncodedInteger(b, uint64(len(s)))
|
||||
return append(b, s...)
|
||||
}
|
||||
|
||||
// reserveBuffer checks cap(buf) and expand buffer to len(buf) + appendSize.
|
||||
// If cap(buf) is not enough, reallocate new buffer.
|
||||
func reserveBuffer(buf []byte, appendSize int) []byte {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue