mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-27 14:16:39 +00:00
163 lines
3.3 KiB
Go
163 lines
3.3 KiB
Go
|
package sqlite3
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/ncruces/go-sqlite3/internal/util"
|
||
|
)
|
||
|
|
||
|
// Error wraps an SQLite Error Code.
|
||
|
//
|
||
|
// https://sqlite.org/c3ref/errcode.html
|
||
|
type Error struct {
|
||
|
str string
|
||
|
msg string
|
||
|
sql string
|
||
|
code uint64
|
||
|
}
|
||
|
|
||
|
// 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 ExtendedErrorCode(e.code)
|
||
|
}
|
||
|
|
||
|
// Error implements the error interface.
|
||
|
func (e *Error) Error() string {
|
||
|
var b strings.Builder
|
||
|
b.WriteString("sqlite3: ")
|
||
|
|
||
|
if e.str != "" {
|
||
|
b.WriteString(e.str)
|
||
|
} else {
|
||
|
b.WriteString(strconv.Itoa(int(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
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// Timeout returns true for [BUSY_TIMEOUT] errors.
|
||
|
func (e ExtendedErrorCode) Timeout() bool {
|
||
|
return e == BUSY_TIMEOUT
|
||
|
}
|
||
|
|
||
|
func errorCode(err error, def ErrorCode) (msg string, code uint32) {
|
||
|
switch code := err.(type) {
|
||
|
case nil:
|
||
|
return "", _OK
|
||
|
case ErrorCode:
|
||
|
return "", uint32(code)
|
||
|
case xErrorCode:
|
||
|
return "", uint32(code)
|
||
|
case *Error:
|
||
|
return code.msg, uint32(code.code)
|
||
|
}
|
||
|
|
||
|
var ecode ErrorCode
|
||
|
var xcode xErrorCode
|
||
|
switch {
|
||
|
case errors.As(err, &xcode):
|
||
|
code = uint32(xcode)
|
||
|
case errors.As(err, &ecode):
|
||
|
code = uint32(ecode)
|
||
|
default:
|
||
|
code = uint32(def)
|
||
|
}
|
||
|
return err.Error(), code
|
||
|
}
|