Skip to content

Commit

Permalink
Merge branch 'master' into RaduBerinde-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
knz committed Sep 25, 2019
2 parents 092b971 + 6a63f8a commit 928808a
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -2,7 +2,7 @@ language: go

go:
- 1.x
- 1.8.x
- 1.13.x

script:
- go test -p 1 -v ./...
Expand Down
3 changes: 2 additions & 1 deletion crdb/README.md
Expand Up @@ -6,7 +6,8 @@ retries (as required by CockroachDB).

Note that unfortunately there is no generic way of extracting a pg error code;
the library has to recognize driver-dependent error types. We currently support
`github.com/lib/pq` and `github.com/jackc/pgx`.
`github.com/lib/pq` and `github.com/jackc/pgconn` (which is used by
`github.com/jackc/pgx/v4`; previous pgx versions are not supported).

Note for developers: if you make any changes here (especially if they modify public
APIs), please verify that the code in https://github.com/cockroachdb/examples-go
Expand Down
36 changes: 32 additions & 4 deletions crdb/error.go
Expand Up @@ -11,19 +11,47 @@ type ErrorCauser interface {
Cause() error
}

// UnwrappableError describes errors compatible with errors.Unwrap.
type UnwrappableError interface {
// Unwrap returns the proximate cause of this error.
Unwrap() error
}

// Unwrap is equivalent to errors.Unwrap. It's implemented here to maintain
// compatibility with Go versions before 1.13 (when the errors package was
// introduced).
// It returns the result of calling the Unwrap method on err, if err's type
// implements UnwrappableError.
// Otherwise, Unwrap returns nil.
func Unwrap(err error) error {
u, ok := err.(UnwrappableError)
if !ok {
return nil
}
return u.Unwrap()
}

// errorCause returns the original cause of the error, if possible. An error has
// a proximate cause if it implements ErrorCauser; the original cause is the
// first error in the cause chain that does not implement ErrorCauser.
//
// errorCause is intentionally equivalent to pkg/errors.Cause.
// a proximate cause if it's type is compatible with Go's errors.Unwrap() (and
// also, for legacy reasons, if it implements ErrorCauser); the original cause
// is the bottom of the causal chain.
func errorCause(err error) error {
// First handle errors implementing ErrorCauser.
for err != nil {
cause, ok := err.(ErrorCauser)
if !ok {
break
}
err = cause.Cause()
}
// Then handle go1.13+ error wrapping.
for {
cause := Unwrap(err)
if cause == nil {
break
}
err = cause
}
return err
}

Expand Down
4 changes: 2 additions & 2 deletions crdb/tx.go
Expand Up @@ -20,7 +20,7 @@ import (
"context"
"database/sql"

"github.com/jackc/pgx"
"github.com/jackc/pgconn"
"github.com/lib/pq"
)

Expand Down Expand Up @@ -143,7 +143,7 @@ func errCode(err error) string {
case *pq.Error:
return string(t.Code)

case pgx.PgError:
case *pgconn.PgError:
return t.Code

default:
Expand Down
22 changes: 21 additions & 1 deletion crdb/tx_test.go
Expand Up @@ -95,8 +95,16 @@ INSERT INTO d.t (acct, balance) VALUES (1, 100), (2, 100);
runTxn := func(wg *sync.WaitGroup, iter *int) <-chan error {
errCh := make(chan error, 1)
go func() {

*iter = 0
errCh <- executeTxFn(context.Background(), db, nil, func(tx *sql.Tx) error {
errCh <- executeTxFn(context.Background(), db, nil, func(tx *sql.Tx) (retErr error) {
defer func() {
if retErr == nil {
return
}
// Wrap the error so that we test the library's unwrapping.
retErr = testError{cause: retErr}
}()
*iter++
bal1, bal2, err := getBalances(tx)
if err != nil {
Expand Down Expand Up @@ -150,3 +158,15 @@ UPDATE d.t SET balance=balance-100 WHERE acct=2;
"got acct1=%d, acct2=%d: %s", bal1, bal2, err)
}
}

type testError struct {
cause error
}

func (t testError) Error() string {
return "test error"
}

func (t testError) Unwrap() error {
return t.cause
}

0 comments on commit 928808a

Please sign in to comment.