Files
RemLink/internal/database/db.go
T
qsc20001102 142e5dc7d6
ci / Go checks (ubuntu-latest) (push) Has been cancelled
ci / Go checks (windows-latest) (push) Has been cancelled
初版功能完成
2026-08-29 13:12:17 +08:00

54 lines
1.3 KiB
Go

// Package database owns SQLite setup, migrations, and persistence repositories.
package database
import (
"context"
"database/sql"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
_ "modernc.org/sqlite"
)
// Open creates the parent directory, opens SQLite, enables required pragmas,
// runs embedded migrations, and verifies connectivity.
func Open(ctx context.Context, path string) (*sql.DB, error) {
if strings.TrimSpace(path) == "" {
return nil, errors.New("database path must not be empty")
}
if path != ":memory:" {
if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil {
return nil, fmt.Errorf("create database directory: %w", err)
}
}
dsn := path
if path != ":memory:" {
dsn = "file:" + filepath.ToSlash(path)
}
separator := "?"
if strings.Contains(dsn, "?") {
separator = "&"
}
dsn += separator + "_pragma=foreign_keys(1)&_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)"
db, err := sql.Open("sqlite", dsn)
if err != nil {
return nil, fmt.Errorf("open SQLite: %w", err)
}
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
if err := db.PingContext(ctx); err != nil {
db.Close()
return nil, fmt.Errorf("ping SQLite: %w", err)
}
if err := Migrate(ctx, db); err != nil {
db.Close()
return nil, err
}
return db, nil
}