mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 10:12:26 -05:00 
			
		
		
		
	Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4075 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
		
			
				
	
	
		
			164 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package sqlite3
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/ncruces/go-sqlite3/internal/util"
 | |
| )
 | |
| 
 | |
| // Error wraps an SQLite Error Code.
 | |
| //
 | |
| // https://sqlite.org/c3ref/errcode.html
 | |
| type Error struct {
 | |
| 	msg  string
 | |
| 	sql  string
 | |
| 	code res_t
 | |
| }
 | |
| 
 | |
| // Code returns the primary error code for this error.
 | |
| //
 | |
| // https://sqlite.org/rescode.html
 | |
| func (e *Error) Code() ErrorCode {
 | |
| 	return ErrorCode(e.code)
 | |
| }
 | |
| 
 | |
| // ExtendedCode returns the extended error code for this error.
 | |
| //
 | |
| // https://sqlite.org/rescode.html
 | |
| func (e *Error) ExtendedCode() ExtendedErrorCode {
 | |
| 	return xErrorCode(e.code)
 | |
| }
 | |
| 
 | |
| // Error implements the error interface.
 | |
| func (e *Error) Error() string {
 | |
| 	var b strings.Builder
 | |
| 	b.WriteString(util.ErrorCodeString(uint32(e.code)))
 | |
| 
 | |
| 	if e.msg != "" {
 | |
| 		b.WriteString(": ")
 | |
| 		b.WriteString(e.msg)
 | |
| 	}
 | |
| 
 | |
| 	return b.String()
 | |
| }
 | |
| 
 | |
| // Is tests whether this error matches a given [ErrorCode] or [ExtendedErrorCode].
 | |
| //
 | |
| // It makes it possible to do:
 | |
| //
 | |
| //	if errors.Is(err, sqlite3.BUSY) {
 | |
| //		// ... handle BUSY
 | |
| //	}
 | |
| func (e *Error) Is(err error) bool {
 | |
| 	switch c := err.(type) {
 | |
| 	case ErrorCode:
 | |
| 		return c == e.Code()
 | |
| 	case ExtendedErrorCode:
 | |
| 		return c == e.ExtendedCode()
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // As converts this error to an [ErrorCode] or [ExtendedErrorCode].
 | |
| func (e *Error) As(err any) bool {
 | |
| 	switch c := err.(type) {
 | |
| 	case *ErrorCode:
 | |
| 		*c = e.Code()
 | |
| 		return true
 | |
| 	case *ExtendedErrorCode:
 | |
| 		*c = e.ExtendedCode()
 | |
| 		return true
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // Temporary returns true for [BUSY] errors.
 | |
| func (e *Error) Temporary() bool {
 | |
| 	return e.Code() == BUSY || e.Code() == INTERRUPT
 | |
| }
 | |
| 
 | |
| // Timeout returns true for [BUSY_TIMEOUT] errors.
 | |
| func (e *Error) Timeout() bool {
 | |
| 	return e.ExtendedCode() == BUSY_TIMEOUT
 | |
| }
 | |
| 
 | |
| // SQL returns the SQL starting at the token that triggered a syntax error.
 | |
| func (e *Error) SQL() string {
 | |
| 	return e.sql
 | |
| }
 | |
| 
 | |
| // Error implements the error interface.
 | |
| func (e ErrorCode) Error() string {
 | |
| 	return util.ErrorCodeString(uint32(e))
 | |
| }
 | |
| 
 | |
| // Temporary returns true for [BUSY] errors.
 | |
| func (e ErrorCode) Temporary() bool {
 | |
| 	return e == BUSY || e == INTERRUPT
 | |
| }
 | |
| 
 | |
| // ExtendedCode returns the extended error code for this error.
 | |
| func (e ErrorCode) ExtendedCode() ExtendedErrorCode {
 | |
| 	return xErrorCode(e)
 | |
| }
 | |
| 
 | |
| // Error implements the error interface.
 | |
| func (e ExtendedErrorCode) Error() string {
 | |
| 	return util.ErrorCodeString(uint32(e))
 | |
| }
 | |
| 
 | |
| // Is tests whether this error matches a given [ErrorCode].
 | |
| func (e ExtendedErrorCode) Is(err error) bool {
 | |
| 	c, ok := err.(ErrorCode)
 | |
| 	return ok && c == ErrorCode(e)
 | |
| }
 | |
| 
 | |
| // As converts this error to an [ErrorCode].
 | |
| func (e ExtendedErrorCode) As(err any) bool {
 | |
| 	c, ok := err.(*ErrorCode)
 | |
| 	if ok {
 | |
| 		*c = ErrorCode(e)
 | |
| 	}
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| // Temporary returns true for [BUSY] errors.
 | |
| func (e ExtendedErrorCode) Temporary() bool {
 | |
| 	return ErrorCode(e) == BUSY || ErrorCode(e) == INTERRUPT
 | |
| }
 | |
| 
 | |
| // Timeout returns true for [BUSY_TIMEOUT] errors.
 | |
| func (e ExtendedErrorCode) Timeout() bool {
 | |
| 	return e == BUSY_TIMEOUT
 | |
| }
 | |
| 
 | |
| // Code returns the primary error code for this error.
 | |
| func (e ExtendedErrorCode) Code() ErrorCode {
 | |
| 	return ErrorCode(e)
 | |
| }
 | |
| 
 | |
| func errorCode(err error, def ErrorCode) (msg string, code res_t) {
 | |
| 	switch code := err.(type) {
 | |
| 	case nil:
 | |
| 		return "", _OK
 | |
| 	case ErrorCode:
 | |
| 		return "", res_t(code)
 | |
| 	case xErrorCode:
 | |
| 		return "", res_t(code)
 | |
| 	case *Error:
 | |
| 		return code.msg, res_t(code.code)
 | |
| 	}
 | |
| 
 | |
| 	var ecode ErrorCode
 | |
| 	var xcode xErrorCode
 | |
| 	switch {
 | |
| 	case errors.As(err, &xcode):
 | |
| 		code = res_t(xcode)
 | |
| 	case errors.As(err, &ecode):
 | |
| 		code = res_t(ecode)
 | |
| 	default:
 | |
| 		code = res_t(def)
 | |
| 	}
 | |
| 	return err.Error(), code
 | |
| }
 |