61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package database
|
|
|
|
import (
|
|
domainUpdate "RenewCMS/internal/domain/update"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
const DriverSQLite = "sqlite"
|
|
|
|
const (
|
|
sqliteBusyTimeoutMs = 5000
|
|
sqliteResultBusy = 5
|
|
sqliteResultLocked = 6
|
|
sqlitePrimaryMask = 0xff
|
|
sqliteUniqueKey = 2067
|
|
sqlitePrimaryKey = 1555
|
|
)
|
|
|
|
type sqliteDriver struct{}
|
|
|
|
func SQLiteDSN(dbName string) string {
|
|
return fmt.Sprintf("%s?_pragma=busy_timeout(%d)", dbName, sqliteBusyTimeoutMs)
|
|
}
|
|
|
|
func (sqliteDriver) Open(file string) (*gorm.DB, error) {
|
|
if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil {
|
|
return nil, fmt.Errorf("unable to create necessary subdirectories: %w", err)
|
|
}
|
|
return gorm.Open(sqlite.Open(SQLiteDSN(file)), &gorm.Config{})
|
|
}
|
|
|
|
func (sqliteDriver) NewBackup(db *gorm.DB, directory string, now func() time.Time) domainUpdate.DatabaseBackup {
|
|
return NewSQLiteBackup(db, directory, now)
|
|
}
|
|
|
|
func (sqliteDriver) IsLockContention(err error) bool {
|
|
code, ok := sqliteCode(err)
|
|
primary := code & sqlitePrimaryMask
|
|
return ok && (primary == sqliteResultBusy || primary == sqliteResultLocked)
|
|
}
|
|
|
|
func (sqliteDriver) IsUniqueViolation(err error) bool {
|
|
code, ok := sqliteCode(err)
|
|
return ok && (code == sqliteUniqueKey || code == sqlitePrimaryKey)
|
|
}
|
|
|
|
func sqliteCode(err error) (int, bool) {
|
|
var coded interface{ Code() int }
|
|
if !errors.As(err, &coded) {
|
|
return 0, false
|
|
}
|
|
return coded.Code(), true
|
|
}
|