Skip to content

Commit

Permalink
Merge branch 'master' into cr4
Browse files Browse the repository at this point in the history
  • Loading branch information
Brigitte Lamarche committed Jul 23, 2018
2 parents 26ea544 + 422ab6f commit f339392
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 16 deletions.
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go:
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- master

before_install:
Expand All @@ -21,7 +22,7 @@ matrix:
- env: DB=MYSQL57
sudo: required
dist: trusty
go: 1.9.x
go: 1.10.x
services:
- docker
before_install:
Expand All @@ -43,7 +44,7 @@ matrix:
- env: DB=MARIA55
sudo: required
dist: trusty
go: 1.9.x
go: 1.10.x
services:
- docker
before_install:
Expand All @@ -65,7 +66,7 @@ matrix:
- env: DB=MARIA10_1
sudo: required
dist: trusty
go: 1.9.x
go: 1.10.x
services:
- docker
before_install:
Expand All @@ -87,6 +88,6 @@ matrix:
script:
- go test -v -covermode=count -coverprofile=coverage.out
- go vet ./...
- test -z "$(gofmt -d -s . | tee /dev/stderr)"
- .travis/gofmt.sh
after_script:
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci
7 changes: 7 additions & 0 deletions .travis/gofmt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
set -ev

# Only check for go1.10+ since the gofmt style changed
if [[ $(go version) =~ go1\.([0-9]+) ]] && ((${BASH_REMATCH[1]} >= 10)); then
test -z "$(gofmt -d -s . | tee /dev/stderr)"
fi
5 changes: 4 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

Aaron Hopkins <go-sql-driver at die.net>
Achille Roussel <achille.roussel at gmail.com>
Alexey Palazhchenko <alexey.palazhchenko at gmail.com>
Andrew Reid <andrew.reid at tixtrack.com>
Arne Hormann <arnehormann at gmail.com>
Asta Xie <xiemengjun at gmail.com>
B Lamarche <blam413 at gmail.com>
Expand Down Expand Up @@ -62,8 +64,8 @@ Paul Bonser <misterpib at gmail.com>
Peter Schultz <peter.schultz at classmarkets.com>
Rebecca Chin <rchin at pivotal.io>
Reed Allman <rdallman10 at gmail.com>
Runrioter Wung <runrioter at gmail.com>
Robert Russell <robert at rrbrussell.com>
Runrioter Wung <runrioter at gmail.com>
Shuode Li <elemount at qq.com>
Soroush Pour <me at soroushjp.com>
Stan Putrya <root.vagner at gmail.com>
Expand All @@ -80,5 +82,6 @@ Counting Ltd.
Google Inc.
InfoSum Ltd.
Keybase Inc.
Percona LLC
Pivotal Inc.
Stripe Inc.
8 changes: 8 additions & 0 deletions driver_go18_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -796,3 +796,11 @@ func TestRowsColumnTypes(t *testing.T) {
})
}
}

func TestValuerWithValueReceiverGivenNilValue(t *testing.T) {
runTests(t, dsn, func(dbt *DBTest) {
dbt.mustExec("CREATE TABLE test (value VARCHAR(255))")
dbt.db.Exec("INSERT INTO test VALUES (?)", (*testValuer)(nil))
// This test will panic on the INSERT if ConvertValue() does not check for typed nil before calling Value()
})
}
28 changes: 28 additions & 0 deletions driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,34 @@ func TestString(t *testing.T) {
})
}

func TestRawBytes(t *testing.T) {
runTests(t, dsn, func(dbt *DBTest) {
v1 := []byte("aaa")
v2 := []byte("bbb")
rows := dbt.mustQuery("SELECT ?, ?", v1, v2)
if rows.Next() {
var o1, o2 sql.RawBytes
if err := rows.Scan(&o1, &o2); err != nil {
dbt.Errorf("Got error: %v", err)
}
if !bytes.Equal(v1, o1) {
dbt.Errorf("expected %v, got %v", v1, o1)
}
if !bytes.Equal(v2, o2) {
dbt.Errorf("expected %v, got %v", v2, o2)
}
// https://github.com/go-sql-driver/mysql/issues/765
// Appending to RawBytes shouldn't overwrite next RawBytes.
o1 = append(o1, "xyzzy"...)
if !bytes.Equal(v2, o2) {
dbt.Errorf("expected %v, got %v", v2, o2)
}
} else {
dbt.Errorf("no data")
}
})
}

type testValuer struct {
value string
}
Expand Down
1 change: 0 additions & 1 deletion dsn.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ 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
Compression bool // Compress packets
}

// NewConfig creates a new Config and sets default values.
Expand Down
41 changes: 37 additions & 4 deletions statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,25 @@ func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {

type converter struct{}

// ConvertValue mirrors the reference/default converter in database/sql/driver
// with _one_ exception. We support uint64 with their high bit and the default
// implementation does not. This function should be kept in sync with
// database/sql/driver defaultConverter.ConvertValue() except for that
// deliberate difference.
func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
if driver.IsValue(v) {
return v, nil
}

if v != nil {
if valuer, ok := v.(driver.Valuer); ok {
return valuer.Value()
if vr, ok := v.(driver.Valuer); ok {
sv, err := callValuerValue(vr)
if err != nil {
return nil, err
}
if !driver.IsValue(sv) {
return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
}
return sv, nil
}

rv := reflect.ValueOf(v)
Expand All @@ -149,8 +159,9 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
// indirect pointers
if rv.IsNil() {
return nil, nil
} else {
return c.ConvertValue(rv.Elem().Interface())
}
return c.ConvertValue(rv.Elem().Interface())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int(), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
Expand All @@ -176,3 +187,25 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
}
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}

var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()

// callValuerValue returns vr.Value(), with one exception:
// If vr.Value is an auto-generated method on a pointer type and the
// pointer is nil, it would panic at runtime in the panicwrap
// method. Treat it like nil instead.
//
// This is so people can implement driver.Value on value types and
// still use nil pointers to those types to mean nil/NULL, just like
// string/*string.
//
// This is an exact copy of the same-named unexported function from the
// database/sql package.
func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
rv.IsNil() &&
rv.Type().Elem().Implements(valuerReflectType) {
return nil, nil
}
return vr.Value()
}
4 changes: 2 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ func readLengthEncodedString(b []byte) ([]byte, bool, int, error) {

// Check data length
if len(b) >= n {
return b[n-int(num) : n], false, n, nil
return b[n-int(num) : n : n], false, n, nil
}
return nil, false, n, io.EOF
}
Expand Down Expand Up @@ -800,7 +800,7 @@ func (ab *atomicBool) TrySet(value bool) bool {
return atomic.SwapUint32(&ab.value, 0) > 0
}

// atomicBool is a wrapper for atomically accessed error values
// atomicError is a wrapper for atomically accessed error values
type atomicError struct {
_noCopy noCopy
value atomic.Value
Expand Down
3 changes: 2 additions & 1 deletion utils_go18.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
)

func cloneTLSConfig(c *tls.Config) *tls.Config {
Expand Down Expand Up @@ -44,6 +45,6 @@ func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
case sql.LevelSerializable:
return "SERIALIZABLE", nil
default:
return "", errors.New("mysql: unsupported isolation level: " + string(level))
return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
}
}
9 changes: 6 additions & 3 deletions utils_go18_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
)

func TestIsolationLevelMapping(t *testing.T) {

data := []struct {
level driver.IsolationLevel
expected string
Expand Down Expand Up @@ -47,8 +46,12 @@ func TestIsolationLevelMapping(t *testing.T) {
}

// check unsupported mapping
if actual, err := mapIsolationLevel(driver.IsolationLevel(sql.LevelLinearizable)); actual != "" || err == nil {
expectedErr := "mysql: unsupported isolation level: 7"
actual, err := mapIsolationLevel(driver.IsolationLevel(sql.LevelLinearizable))
if actual != "" || err == nil {
t.Fatal("Expected error on unsupported isolation level")
}

if err.Error() != expectedErr {
t.Fatalf("Expected error to be %q, got %q", expectedErr, err)
}
}

0 comments on commit f339392

Please sign in to comment.