// Package db 负责 GORM 数据库连接的初始化与迁移注册。 package db import ( "fmt" "log/slog" "os" "path/filepath" "github.com/glebarez/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" "github.com/kennethcheng/fuellog-api/internal/model" ) // Open 打开 SQLite 数据库连接,并确保目标目录存在。 // // 设计要点: // - 使用 pure-Go glebarez/sqlite,避免 CGO;Windows / Docker 都友好 // - 日志走 slog,关闭 GORM 默认的 stdout 输出 // - 启用 WAL + 外键约束,提升并发与一致性 func Open(path string) (*gorm.DB, error) { if dir := filepath.Dir(path); dir != "" { if err := os.MkdirAll(dir, 0o755); err != nil { return nil, fmt.Errorf("ensure db dir: %w", err) } } gormLogger := logger.New( slog.NewLogLogger(slog.Default().Handler(), slog.LevelWarn), logger.Config{ LogLevel: logger.Warn, Colorful: false, }, ) dsn := fmt.Sprintf("file:%s?_pragma=journal_mode(WAL)&_pragma=foreign_keys(ON)&_pragma=busy_timeout(5000)", path) g, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{Logger: gormLogger}) if err != nil { return nil, fmt.Errorf("open sqlite: %w", err) } return g, nil } // Migrate 在数据库上注册所有模型。Phase 1.2 之前,业务表只读;Phase 1.2 // 起每次 schema 变更必须追加迁移文件,不得依赖此处注册。 func Migrate(g *gorm.DB) error { return g.AutoMigrate( &model.Vehicle{}, &model.RefuelRecord{}, ) }