76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package db
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
var (
|
|
ErrNotInDB = errors.New("not in db")
|
|
ErrItemIsDeleted = errors.New("item is deleted")
|
|
ErrForeignKeyViolation = errors.New("foreign key constraint failed")
|
|
ErrDatabaseAlreadyExists = errors.New("target already exists")
|
|
)
|
|
|
|
type ForeignKey interface {
|
|
~uint64 | ~string
|
|
}
|
|
|
|
type ForeignKeyError[T ForeignKey] struct {
|
|
Field string
|
|
TargetTable string
|
|
FkValue T
|
|
}
|
|
|
|
func NewForeignKeyError[T ForeignKey](field, table string, fkValue T) ForeignKeyError[T] {
|
|
return ForeignKeyError[T]{
|
|
Field: field,
|
|
TargetTable: table,
|
|
FkValue: fkValue,
|
|
}
|
|
}
|
|
|
|
func (e ForeignKeyError[T]) Error() string {
|
|
return fmt.Sprintf(`%s: fk field %q (to %q) with value "%v"`,
|
|
ErrForeignKeyViolation.Error(), e.Field, e.TargetTable, e.FkValue,
|
|
)
|
|
}
|
|
|
|
// Unwrap returns the sentinel error-- permits the use of errors.Is for convenience
|
|
func (e ForeignKeyError[T]) Unwrap() error {
|
|
return ErrForeignKeyViolation
|
|
}
|
|
|
|
// -------------
|
|
// SQLite errors
|
|
// -------------
|
|
|
|
// IsSqliteFkError checks whether an error is a SQLite foreign key constraint violation.
|
|
func IsSqliteFkError(err error) bool {
|
|
var sqliteErr sqlite3.Error
|
|
if !errors.As(err, &sqliteErr) {
|
|
return false
|
|
}
|
|
return errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintForeignKey)
|
|
}
|
|
|
|
// IsSqliteUniqError checks whether an error is a SQLite unique constraint violation.
|
|
func IsSqliteUniqError(err error) bool {
|
|
var sqliteErr sqlite3.Error
|
|
if !errors.As(err, &sqliteErr) {
|
|
return false
|
|
}
|
|
return errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintUnique)
|
|
}
|
|
|
|
// IsSqliteNotNullError checks whether an error is a SQLite not null constraint violation.
|
|
func IsSqliteNotNullError(err error) bool {
|
|
var sqliteErr sqlite3.Error
|
|
if !errors.As(err, &sqliteErr) {
|
|
return false
|
|
}
|
|
return errors.Is(sqliteErr.ExtendedCode, sqlite3.ErrConstraintNotNull)
|
|
}
|