Files
db-sqlite/errors.go
T

47 lines
1.4 KiB
Go
Raw Normal View History

package sqlite
import (
"database/sql"
"errors"
"code.nochebuena.dev/einherjar/core/xerrors"
)
// coder is the duck-type interface for SQLite extended error codes.
// modernc.org/sqlite errors implement this interface.
type coder interface{ Code() int }
const (
sqliteConstraintPrimaryKey = 1555
sqliteConstraintUnique = 2067
sqliteConstraintForeignKey = 787
)
// HandleError maps database/sql and SQLite errors to typed [xerrors] values.
// Returns nil when err is nil. Also available as [Provider.HandleError].
//
// Mapped codes:
// - sql.ErrNoRows → ErrNotFound
// - SQLITE_CONSTRAINT_UNIQUE (2067) → ErrAlreadyExists
// - SQLITE_CONSTRAINT_PRIMARYKEY (1555)→ ErrAlreadyExists
// - SQLITE_CONSTRAINT_FOREIGNKEY (787) → ErrInvalidInput
// - all others → ErrInternal
func HandleError(err error) error {
if err == nil {
return nil
}
if errors.Is(err, sql.ErrNoRows) {
return xerrors.New(xerrors.ErrNotFound, "record not found").WithError(err)
}
var ce coder
if errors.As(err, &ce) {
switch ce.Code() {
case sqliteConstraintUnique, sqliteConstraintPrimaryKey:
return xerrors.New(xerrors.ErrAlreadyExists, "record already exists").WithError(err)
case sqliteConstraintForeignKey:
return xerrors.New(xerrors.ErrInvalidInput, "data integrity violation").WithError(err)
}
}
return xerrors.New(xerrors.ErrInternal, "unexpected database error").WithError(err)
}