github.com/movsb/taorm@v0.0.0-20201209183410-91bafb0b22a6/taorm/error.go (about)

     1  package taorm
     2  
     3  import (
     4  	"database/sql"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  	"regexp"
     9  
    10  	"github.com/go-sql-driver/mysql"
    11  )
    12  
    13  var (
    14  	reErr1062 = regexp.MustCompile(`Duplicate entry '([^']*)' for key '([^']+)'`)
    15  )
    16  
    17  // Error all errors wrapper.
    18  type Error struct {
    19  	Err error
    20  	Raw error
    21  }
    22  
    23  func (e Error) Error() string {
    24  	return fmt.Sprintf("taorm error: %v: %v", e.Err, e.Raw)
    25  }
    26  
    27  // WrapError wraps all errors to tao error.
    28  //
    29  // If err is nil, wrapped error is nil too.
    30  func WrapError(err error) error {
    31  	if err == nil {
    32  		return nil
    33  	}
    34  
    35  	// don't wrap again
    36  	if _, ok := err.(*Error); ok {
    37  		return err
    38  	}
    39  
    40  	// mysql errors
    41  	if myErr, ok := err.(*mysql.MySQLError); ok {
    42  		switch myErr.Number {
    43  		case 1062:
    44  			matches := reErr1062.FindStringSubmatch(myErr.Message)
    45  			return &Error{
    46  				Err: &DupKeyError{
    47  					Key:   matches[2],
    48  					Value: matches[1],
    49  				},
    50  				Raw: myErr,
    51  			}
    52  		}
    53  	}
    54  
    55  	// official error constants
    56  	switch err {
    57  	case sql.ErrNoRows:
    58  		return &Error{Err: &NotFoundError{}, Raw: err}
    59  	}
    60  
    61  	// taorm error constants
    62  	switch err {
    63  	case ErrInternal:
    64  	case ErrNoWhere:
    65  	case ErrNoFields:
    66  	case ErrInvalidOut:
    67  		return &Error{Err: ErrInternal, Raw: err}
    68  	}
    69  
    70  	// taorm detailed errors
    71  	switch err.(type) {
    72  	case *NoPlaceToSaveFieldError:
    73  		return &Error{Err: ErrInternal, Raw: err}
    74  	case *NotStructError:
    75  		return &Error{Err: ErrInternal, Raw: err}
    76  	}
    77  
    78  	// unhandled errors
    79  	return &Error{Err: ErrInternal, Raw: err}
    80  }
    81  
    82  var (
    83  	// ErrInternal ...
    84  	ErrInternal = errors.New("internal error")
    85  	// ErrNoWhere ...
    86  	ErrNoWhere = errors.New("no wheres")
    87  	// ErrNoFields ...
    88  	ErrNoFields = errors.New("no fields")
    89  	// ErrInvalidOut ...
    90  	ErrInvalidOut = errors.New("invalid out")
    91  )
    92  
    93  // NotFoundError ...
    94  type NotFoundError struct {
    95  }
    96  
    97  func (e NotFoundError) Error() string {
    98  	return "Not Found"
    99  }
   100  
   101  // DupKeyError ...
   102  type DupKeyError struct {
   103  	Key   string
   104  	Value string
   105  }
   106  
   107  func (e DupKeyError) Error() string {
   108  	return fmt.Sprintf("DupKeyError: key=%s,value=%s", e.Key, e.Value)
   109  }
   110  
   111  // NoPlaceToSaveFieldError ...
   112  type NoPlaceToSaveFieldError struct {
   113  	Field string
   114  }
   115  
   116  func (e NoPlaceToSaveFieldError) Error() string {
   117  	return fmt.Sprintf("NoPlaceToSaveFieldError: `%s'", e.Field)
   118  }
   119  
   120  // NotStructError ...
   121  type NotStructError struct {
   122  	Kind reflect.Kind
   123  }
   124  
   125  func (e NotStructError) Error() string {
   126  	return fmt.Sprintf("taorm: not a struct: `%v'", e.Kind)
   127  }
   128  
   129  // IsNotFoundError ...
   130  func IsNotFoundError(err error) bool {
   131  	if err == sql.ErrNoRows {
   132  		return true
   133  	}
   134  	if te, ok := err.(*Error); ok {
   135  		if te.Raw == sql.ErrNoRows {
   136  			return true
   137  		}
   138  	}
   139  	return false
   140  }