Files
sqlite3/error.go

173 lines
3.5 KiB
Go
Raw Normal View History

2023-01-12 13:43:35 +00:00
package sqlite3
import (
2023-11-16 01:16:38 +00:00
"errors"
2023-01-12 13:43:35 +00:00
"strconv"
"strings"
2023-05-18 16:00:34 +01:00
"github.com/ncruces/go-sqlite3/internal/util"
2023-01-12 13:43:35 +00:00
)
2023-02-09 16:40:48 +00:00
// Error wraps an SQLite Error Code.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/c3ref/errcode.html
2023-01-12 13:43:35 +00:00
type Error struct {
2023-02-09 16:40:48 +00:00
str string
msg string
2023-02-10 16:42:49 +00:00
sql string
2023-04-11 15:33:38 +01:00
code uint64
2023-01-12 13:43:35 +00:00
}
2023-02-09 16:40:48 +00:00
// Code returns the primary error code for this error.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/rescode.html
2023-02-09 16:40:48 +00:00
func (e *Error) Code() ErrorCode {
return ErrorCode(e.code)
}
// ExtendedCode returns the extended error code for this error.
//
2023-11-09 16:35:45 +00:00
// https://sqlite.org/rescode.html
2023-02-09 16:40:48 +00:00
func (e *Error) ExtendedCode() ExtendedErrorCode {
return ExtendedErrorCode(e.code)
}
// Error implements the error interface.
2023-01-21 00:33:46 +00:00
func (e *Error) Error() string {
2023-01-12 13:43:35 +00:00
var b strings.Builder
b.WriteString("sqlite3: ")
if e.str != "" {
b.WriteString(e.str)
} else {
2023-02-09 16:40:48 +00:00
b.WriteString(strconv.Itoa(int(e.code)))
2023-01-12 13:43:35 +00:00
}
if e.msg != "" {
2023-12-06 15:39:26 +00:00
b.WriteString(": ")
2023-01-12 13:43:35 +00:00
b.WriteString(e.msg)
}
return b.String()
}
2023-01-19 14:31:32 +00:00
2023-02-25 15:11:07 +00:00
// Is tests whether this error matches a given [ErrorCode] or [ExtendedErrorCode].
//
2023-03-01 10:34:08 +00:00
// It makes it possible to do:
2023-02-25 15:11:07 +00:00
//
// 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
}
2023-06-30 12:25:07 +01:00
// 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
}
2023-02-20 13:38:03 +00:00
// Temporary returns true for [BUSY] errors.
func (e *Error) Temporary() bool {
return e.Code() == BUSY
}
2023-02-25 15:11:07 +00:00
// Timeout returns true for [BUSY_TIMEOUT] errors.
func (e *Error) Timeout() bool {
return e.ExtendedCode() == BUSY_TIMEOUT
}
2023-02-10 16:42:49 +00:00
// SQL returns the SQL starting at the token that triggered a syntax error.
func (e *Error) SQL() string {
return e.sql
}
2023-02-25 15:11:07 +00:00
// Error implements the error interface.
func (e ErrorCode) Error() string {
2023-05-18 16:00:34 +01:00
return util.ErrorCodeString(uint32(e))
2023-02-25 15:11:07 +00:00
}
// Temporary returns true for [BUSY] errors.
func (e ErrorCode) Temporary() bool {
return e == BUSY
}
2024-11-06 11:45:20 +00:00
// ExtendedCode returns the extended error code for this error.
func (e ErrorCode) ExtendedCode() ExtendedErrorCode {
return ExtendedErrorCode(e)
}
2023-02-25 15:11:07 +00:00
// Error implements the error interface.
func (e ExtendedErrorCode) Error() string {
2023-05-18 16:00:34 +01:00
return util.ErrorCodeString(uint32(e))
2023-02-25 15:11:07 +00:00
}
// 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)
}
2023-06-30 12:25:07 +01:00
// 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
}
2023-02-25 15:11:07 +00:00
// 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
}
2023-11-16 01:16:38 +00:00
2024-11-06 11:45:20 +00:00
// Code returns the primary error code for this error.
func (e ExtendedErrorCode) Code() ErrorCode {
return ErrorCode(e)
}
2023-11-21 13:40:55 +00:00
func errorCode(err error, def ErrorCode) (msg string, code uint32) {
switch code := err.(type) {
2024-01-11 02:18:12 +00:00
case nil:
return "", _OK
2023-11-21 13:40:55 +00:00
case ErrorCode:
return "", uint32(code)
2024-01-11 02:18:12 +00:00
case xErrorCode:
2023-11-21 13:40:55 +00:00
return "", uint32(code)
2023-12-05 16:11:56 +00:00
case *Error:
return code.msg, uint32(code.code)
2023-11-21 13:40:55 +00:00
}
2023-11-16 01:16:38 +00:00
var ecode ErrorCode
var xcode xErrorCode
switch {
case errors.As(err, &xcode):
2023-11-21 13:40:55 +00:00
code = uint32(xcode)
2023-11-16 01:16:38 +00:00
case errors.As(err, &ecode):
2023-11-21 13:40:55 +00:00
code = uint32(ecode)
default:
code = uint32(def)
2023-11-16 01:16:38 +00:00
}
2023-11-21 13:40:55 +00:00
return err.Error(), code
2023-11-16 01:16:38 +00:00
}