Skip to content

Commit 4cdff28

Browse files
author
Brigitte Lamarche
committed
2 parents a0cf94b + ee359f9 commit 4cdff28

15 files changed

+215
-305
lines changed

.travis.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@ go:
55
- 1.6
66
- 1.7
77
- 1.8
8+
- 1.9
89
- tip
910

1011
before_install:
1112
- go get golang.org/x/tools/cmd/cover
1213
- go get github.com/mattn/goveralls
1314

15+
before_script:
16+
- echo -e "[server]\ninnodb_log_file_size=256MB\ninnodb_buffer_pool_size=512MB\nmax_allowed_packet=16MB" | sudo tee -a /etc/mysql/my.cnf
17+
- sudo service mysql restart
18+
- .travis/wait_mysql.sh
19+
- mysql -e 'create database gotest;'
20+
1421
matrix:
1522
include:
1623
- env: DB=MYSQL57
1724
sudo: required
1825
dist: trusty
19-
go: 1.8
26+
go: 1.9
2027
services:
2128
- docker
2229
before_install:
@@ -38,7 +45,7 @@ matrix:
3845
- env: DB=MARIA55
3946
sudo: required
4047
dist: trusty
41-
go: 1.8
48+
go: 1.9
4249
services:
4350
- docker
4451
before_install:
@@ -60,7 +67,7 @@ matrix:
6067
- env: DB=MARIA10_1
6168
sudo: required
6269
dist: trusty
63-
go: 1.8
70+
go: 1.9
6471
services:
6572
- docker
6673
before_install:
@@ -79,9 +86,6 @@ matrix:
7986
- export MYSQL_TEST_ADDR=127.0.0.1:3307
8087
- export MYSQL_TEST_CONCURRENT=1
8188

82-
83-
before_script:
84-
- mysql -e 'create database gotest;'
8589
script:
8690
- go test -v -covermode=count -coverprofile=coverage.out
8791
- go vet ./...

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Paul Bonser <misterpib at gmail.com>
5757
Peter Schultz <peter.schultz at classmarkets.com>
5858
Rebecca Chin <rchin at pivotal.io>
5959
Runrioter Wung <runrioter at gmail.com>
60+
Shuode Li <elemount at qq.com>
6061
Soroush Pour <me at soroushjp.com>
6162
Stan Putrya <root.vagner at gmail.com>
6263
Stanley Gunawan <gunawan.stanley at gmail.com>

README.md

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ A MySQL-Driver for Go's [database/sql](https://golang.org/pkg/database/sql/) pac
4747
## Installation
4848
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:
4949
```bash
50-
$ go get github.com/go-sql-driver/mysql
50+
$ go get -u github.com/go-sql-driver/mysql
5151
```
5252
Make sure [Git is installed](https://git-scm.com/downloads) on your machine and in your system's `PATH`.
5353

@@ -101,7 +101,8 @@ See [net.Dial](https://golang.org/pkg/net/#Dial) for more information which netw
101101
In general you should use an Unix domain socket if available and TCP otherwise for best performance.
102102

103103
#### Address
104-
For TCP and UDP networks, addresses have the form `host:port`.
104+
For TCP and UDP networks, addresses have the form `host[:port]`.
105+
If `port` is omitted, the default port will be used.
105106
If `host` is a literal IPv6 address, it must be enclosed in square brackets.
106107
The functions [net.JoinHostPort](https://golang.org/pkg/net/#JoinHostPort) and [net.SplitHostPort](https://golang.org/pkg/net/#SplitHostPort) manipulate addresses in this form.
107108

@@ -138,9 +139,9 @@ Default: false
138139
```
139140
Type: bool
140141
Valid Values: true, false
141-
Default: false
142+
Default: true
142143
```
143-
`allowNativePasswords=true` allows the usage of the mysql native password method.
144+
`allowNativePasswords=false` disallows the usage of MySQL native password method.
144145

145146
##### `allowOldPasswords`
146147

@@ -293,20 +294,6 @@ supposed to happen, setting this on some MySQL providers (such as AWS Aurora)
293294
is safer for failovers.
294295

295296

296-
##### `strict`
297-
298-
```
299-
Type: bool
300-
Valid Values: true, false
301-
Default: false
302-
```
303-
304-
`strict=true` enables a driver-side strict mode in which MySQL warnings are treated as errors. This mode should not be used in production as it may lead to data corruption in certain situations.
305-
306-
A server-side strict mode, which is safe for production use, can be set via the [`sql_mode`](https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html) system variable.
307-
308-
By default MySQL also treats notes as warnings. Use [`sql_notes=false`](http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sql_notes) to ignore notes.
309-
310297
##### `timeout`
311298

312299
```
@@ -316,6 +303,7 @@ Default: OS default
316303

317304
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"*.
318305

306+
319307
##### `tls`
320308

321309
```
@@ -326,6 +314,7 @@ Default: false
326314

327315
`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).
328316

317+
329318
##### `writeTimeout`
330319

331320
```
@@ -344,9 +333,9 @@ Any other parameters are interpreted as system variables:
344333
* `<string_var>=%27<value>%27`: `SET <string_var>='<value>'`
345334

346335
Rules:
347-
* The values for string variables must be quoted with '
336+
* The values for string variables must be quoted with `'`.
348337
* The values must also be [url.QueryEscape](http://golang.org/pkg/net/url/#QueryEscape)'ed!
349-
(which implies values of string variables must be wrapped with `%27`)
338+
(which implies values of string variables must be wrapped with `%27`).
350339

351340
Examples:
352341
* `autocommit=1`: `SET autocommit=1`
@@ -426,7 +415,7 @@ See the [godoc of Go-MySQL-Driver](https://godoc.org/github.com/go-sql-driver/my
426415

427416

428417
### `time.Time` support
429-
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.
418+
The default internal output type of MySQL `DATE` and `DATETIME` values is `[]byte` which allows you to scan the value into a `[]byte`, `string` or `sql.RawBytes` variable in your program.
430419

431420
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.
432421

@@ -466,13 +455,13 @@ Mozilla summarizes the license scope as follows:
466455
467456

468457
That means:
469-
* You can **use** the **unchanged** source code both in private and commercially
470-
* 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)
471-
* You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**
458+
* You can **use** the **unchanged** source code both in private and commercially.
459+
* 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).
460+
* You **needn't publish** the source code of your library as long as the files licensed under the MPL 2.0 are **unchanged**.
472461

473462
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.
474463

475-
You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE)
464+
You can read the full terms here: [LICENSE](https://raw.github.com/go-sql-driver/mysql/master/LICENSE).
476465

477466
![Go Gopher and MySQL Dolphin](https://raw.github.com/wiki/go-sql-driver/mysql/go-mysql-driver_m.jpg "Golang Gopher transporting the MySQL Dolphin in a wheelbarrow")
478467

benchmark_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,7 @@ func initDB(b *testing.B, useCompression bool, queries ...string) *sql.DB {
5252
db := tb.checkDB(sql.Open("mysql", dsn+comprStr))
5353
for _, query := range queries {
5454
if _, err := db.Exec(query); err != nil {
55-
if w, ok := err.(MySQLWarnings); ok {
56-
b.Logf("warning on %q: %v", query, w)
57-
} else {
58-
b.Fatalf("error on %q: %v", query, err)
59-
}
55+
b.Fatalf("error on %q: %v", query, err)
6056
}
6157
}
6258
return db

connection.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ type mysqlConn struct {
4141
sequence uint8
4242
compressionSequence uint8
4343
parseTime bool
44-
strict bool
4544
reader packetReader
4645
writer io.Writer
4746

@@ -84,17 +83,36 @@ func (mc *mysqlConn) handleParams() (err error) {
8483
return
8584
}
8685

86+
func (mc *mysqlConn) markBadConn(err error) error {
87+
if mc == nil {
88+
return err
89+
}
90+
if err != errBadConnNoWrite {
91+
return err
92+
}
93+
return driver.ErrBadConn
94+
}
95+
8796
func (mc *mysqlConn) Begin() (driver.Tx, error) {
97+
return mc.begin(false)
98+
}
99+
100+
func (mc *mysqlConn) begin(readOnly bool) (driver.Tx, error) {
88101
if mc.closed.IsSet() {
89102
errLog.Print(ErrInvalidConn)
90103
return nil, driver.ErrBadConn
91104
}
92-
err := mc.exec("START TRANSACTION")
105+
var q string
106+
if readOnly {
107+
q = "START TRANSACTION READ ONLY"
108+
} else {
109+
q = "START TRANSACTION"
110+
}
111+
err := mc.exec(q)
93112
if err == nil {
94113
return &mysqlTx{mc}, err
95114
}
96-
97-
return nil, err
115+
return nil, mc.markBadConn(err)
98116
}
99117

100118
func (mc *mysqlConn) Close() (err error) {
@@ -145,7 +163,7 @@ func (mc *mysqlConn) Prepare(query string) (driver.Stmt, error) {
145163
// Send command
146164
err := mc.writeCommandPacketStr(comStmtPrepare, query)
147165
if err != nil {
148-
return nil, err
166+
return nil, mc.markBadConn(err)
149167
}
150168

151169
stmt := &mysqlStmt{
@@ -179,7 +197,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
179197
if buf == nil {
180198
// can not take the buffer. Something must be wrong with the connection
181199
errLog.Print(ErrBusyBuffer)
182-
return "", driver.ErrBadConn
200+
return "", ErrInvalidConn
183201
}
184202
buf = buf[:0]
185203
argPos := 0
@@ -317,14 +335,14 @@ func (mc *mysqlConn) Exec(query string, args []driver.Value) (driver.Result, err
317335
insertId: int64(mc.insertId),
318336
}, err
319337
}
320-
return nil, err
338+
return nil, mc.markBadConn(err)
321339
}
322340

323341
// Internal function to execute commands
324342
func (mc *mysqlConn) exec(query string) error {
325343
// Send command
326344
if err := mc.writeCommandPacketStr(comQuery, query); err != nil {
327-
return err
345+
return mc.markBadConn(err)
328346
}
329347

330348
// Read Result
@@ -393,7 +411,7 @@ func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error)
393411
return rows, err
394412
}
395413
}
396-
return nil, err
414+
return nil, mc.markBadConn(err)
397415
}
398416

399417
// Gets the value of the given MySQL System Variable

connection_go18.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"context"
1515
"database/sql"
1616
"database/sql/driver"
17-
"errors"
1817
)
1918

2019
// Ping implements driver.Pinger interface
@@ -41,15 +40,9 @@ func (mc *mysqlConn) Ping(ctx context.Context) error {
4140

4241
// BeginTx implements driver.ConnBeginTx interface
4342
func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
44-
if opts.ReadOnly {
45-
// TODO: support read-only transactions
46-
return nil, errors.New("mysql: read-only transactions not supported")
47-
}
48-
4943
if err := mc.watchCancel(ctx); err != nil {
5044
return nil, err
5145
}
52-
5346
defer mc.finish()
5447

5548
if sql.IsolationLevel(opts.Isolation) != sql.LevelDefault {
@@ -63,7 +56,7 @@ func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver
6356
}
6457
}
6558

66-
return mc.Begin()
59+
return mc.begin(opts.ReadOnly)
6760
}
6861

6962
func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {

driver.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
6464
return nil, err
6565
}
6666
mc.parseTime = mc.cfg.ParseTime
67-
mc.strict = mc.cfg.Strict
6867

6968
// Connect to Server
7069
if dial, ok := dials[mc.cfg.Net]; ok {

driver_go18_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,3 +520,41 @@ func TestContextBeginIsolationLevel(t *testing.T) {
520520
tx2.Commit()
521521
})
522522
}
523+
524+
func TestContextBeginReadOnly(t *testing.T) {
525+
runTests(t, dsn, func(dbt *DBTest) {
526+
dbt.mustExec("CREATE TABLE test (v INTEGER)")
527+
ctx, cancel := context.WithCancel(context.Background())
528+
defer cancel()
529+
530+
tx, err := dbt.db.BeginTx(ctx, &sql.TxOptions{
531+
ReadOnly: true,
532+
})
533+
if _, ok := err.(*MySQLError); ok {
534+
dbt.Skip("It seems that your MySQL does not support READ ONLY transactions")
535+
return
536+
} else if err != nil {
537+
dbt.Fatal(err)
538+
}
539+
540+
// INSERT queries fail in a READ ONLY transaction.
541+
_, err = tx.ExecContext(ctx, "INSERT INTO test VALUES (1)")
542+
if _, ok := err.(*MySQLError); !ok {
543+
dbt.Errorf("expected MySQLError, got %v", err)
544+
}
545+
546+
// SELECT queries can be executed.
547+
var v int
548+
row := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM test")
549+
if err := row.Scan(&v); err != nil {
550+
dbt.Fatal(err)
551+
}
552+
if v != 0 {
553+
dbt.Errorf("expected val to be 0, got %d", v)
554+
}
555+
556+
if err := tx.Commit(); err != nil {
557+
dbt.Fatal(err)
558+
}
559+
})
560+
}

0 commit comments

Comments
 (0)