mirror of
https://github.com/hanzo-fi/go-libs.git
synced 2026-10-30 20:53:44 +00:00
Migrate all internal usages of github.com/pkg/errors to the Go standard library: errors.New/Is/As map directly to the stdlib equivalents, while errors.Wrap/Wrapf become fmt.Errorf(..., %w, err). github.com/pkg/errors is no longer a direct dependency (remains indirect via watermill). Constraint: errors.Wrap returns nil on nil input; fmt.Errorf does not, so run.go's "executing migration" wrap was rewritten as an explicit nil check Confidence: high Scope-risk: narrow
216 lines
4.5 KiB
Go
216 lines
4.5 KiB
Go
package postgres
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
|
|
"github.com/jackc/pgerrcode"
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
)
|
|
|
|
// ResolveError is an helper to wrap postgres errors into storage errors
|
|
func ResolveError(err error) error {
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return ErrNotFound
|
|
}
|
|
|
|
var pge *pgconn.PgError
|
|
switch {
|
|
case errors.As(err, &pge):
|
|
switch pge.Code {
|
|
case pgerrcode.NotNullViolation, pgerrcode.InvalidTextRepresentation:
|
|
return newErrValidationFailed(pge)
|
|
case pgerrcode.ForeignKeyViolation:
|
|
return newErrFkConstraintFailed(pge)
|
|
case pgerrcode.UniqueViolation:
|
|
return newErrConstraintsFailed(pge)
|
|
case pgerrcode.TooManyConnections:
|
|
return newErrTooManyClient(err)
|
|
case pgerrcode.DeadlockDetected:
|
|
return ErrDeadlockDetected
|
|
case pgerrcode.ReadOnlySQLTransaction:
|
|
return ErrReadOnlyTransaction
|
|
case pgerrcode.SerializationFailure:
|
|
return ErrSerialization
|
|
case pgerrcode.UndefinedTable:
|
|
return ErrMissingTable
|
|
case pgerrcode.InvalidSchemaName:
|
|
return ErrMissingSchema
|
|
case pgerrcode.CheckViolation:
|
|
return newErrCheckViolation(pge)
|
|
case pgerrcode.RaiseException:
|
|
return newErrRaisedException(pge)
|
|
}
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
ErrNotFound = errors.New("not found")
|
|
ErrDeadlockDetected = errors.New("deadlock detected")
|
|
ErrReadOnlyTransaction = errors.New("read-only transaction")
|
|
ErrSerialization = errors.New("serialization error")
|
|
ErrMissingTable = errors.New("missing table")
|
|
ErrMissingSchema = errors.New("missing schema")
|
|
)
|
|
|
|
func IsNotFoundError(err error) bool {
|
|
return errors.Is(err, ErrNotFound)
|
|
}
|
|
|
|
type ErrFKConstraintFailed struct {
|
|
err *pgconn.PgError
|
|
}
|
|
|
|
func (e ErrFKConstraintFailed) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func (e ErrFKConstraintFailed) Is(err error) bool {
|
|
var errFKConstraintFailed ErrFKConstraintFailed
|
|
ok := errors.As(err, &errFKConstraintFailed)
|
|
return ok
|
|
}
|
|
|
|
func (e ErrFKConstraintFailed) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func (e ErrFKConstraintFailed) GetConstraint() string {
|
|
return e.err.ConstraintName
|
|
}
|
|
|
|
func newErrFkConstraintFailed(err *pgconn.PgError) ErrFKConstraintFailed {
|
|
return ErrFKConstraintFailed{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
type ErrValidationFailed struct {
|
|
err *pgconn.PgError
|
|
}
|
|
|
|
func (e ErrValidationFailed) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func (e ErrValidationFailed) Is(err error) bool {
|
|
var errValidationFailed ErrValidationFailed
|
|
ok := errors.As(err, &errValidationFailed)
|
|
return ok
|
|
}
|
|
|
|
func (e ErrValidationFailed) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func (e ErrValidationFailed) Message() string {
|
|
return e.err.Message
|
|
}
|
|
|
|
func newErrValidationFailed(err *pgconn.PgError) ErrValidationFailed {
|
|
return ErrValidationFailed{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
// ErrConstraintsFailed wraps 23505 pg error, meaning uniqueness constraint failed
|
|
type ErrConstraintsFailed struct {
|
|
err *pgconn.PgError
|
|
}
|
|
|
|
func (e ErrConstraintsFailed) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func (e ErrConstraintsFailed) Is(err error) bool {
|
|
var errConstraintsFailed ErrConstraintsFailed
|
|
ok := errors.As(err, &errConstraintsFailed)
|
|
return ok
|
|
}
|
|
|
|
func (e ErrConstraintsFailed) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func (e ErrConstraintsFailed) GetConstraint() string {
|
|
return e.err.ConstraintName
|
|
}
|
|
|
|
func newErrConstraintsFailed(err *pgconn.PgError) ErrConstraintsFailed {
|
|
return ErrConstraintsFailed{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
type ErrCheckViolation struct {
|
|
err *pgconn.PgError
|
|
}
|
|
|
|
func (e ErrCheckViolation) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func (e ErrCheckViolation) Is(err error) bool {
|
|
var errChecks ErrCheckViolation
|
|
ok := errors.As(err, &errChecks)
|
|
return ok
|
|
}
|
|
|
|
func (e ErrCheckViolation) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func newErrCheckViolation(err *pgconn.PgError) ErrCheckViolation {
|
|
return ErrCheckViolation{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
type ErrTooManyClient struct {
|
|
err error
|
|
}
|
|
|
|
func (e ErrTooManyClient) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func newErrTooManyClient(err error) ErrTooManyClient {
|
|
return ErrTooManyClient{
|
|
err: err,
|
|
}
|
|
}
|
|
|
|
type ErrRaisedException struct {
|
|
err *pgconn.PgError
|
|
}
|
|
|
|
func (e ErrRaisedException) Error() string {
|
|
return e.err.Error()
|
|
}
|
|
|
|
func (e ErrRaisedException) Is(err error) bool {
|
|
var errRaisedException ErrRaisedException
|
|
ok := errors.As(err, &errRaisedException)
|
|
return ok
|
|
}
|
|
|
|
func (e ErrRaisedException) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
func (e ErrRaisedException) GetMessage() string {
|
|
return e.err.Message
|
|
}
|
|
|
|
func newErrRaisedException(err *pgconn.PgError) ErrRaisedException {
|
|
return ErrRaisedException{
|
|
err: err,
|
|
}
|
|
}
|