Files
yellowjacket/backend/database/database.go
T
logan 672fe24ee9 fix: use path.Join for embed.FS paths to fix Windows build
filepath.Join uses OS-specific separators (backslash on Windows), but
embed.FS always uses forward slashes. This caused schema file lookups
to fail during Wails binding generation on Windows.
2026-02-13 23:16:57 -06:00

94 lines
2.2 KiB
Go

// Package database provides SQLite database access.
package database
import (
"context"
"database/sql"
"embed"
"fmt"
"io/fs"
"log/slog"
"path"
_ "modernc.org/sqlite" // Register sqlite driver.
"yellowjacket/backend/database/sql/sqlcgen"
"yellowjacket/backend/system"
)
//go:generate go tool sqlc generate
//go:embed sql/schemas/*.sql
var schemas embed.FS
// DB wraps the SQLite database connection and queries.
type DB struct {
db *sql.DB
Ctx context.Context
Queries *sqlcgen.Queries
logger *slog.Logger
}
// NewDB opens the database and applies schema migrations.
func NewDB(logger *slog.Logger) (*DB, error) {
dbCtx := context.Background()
userDataDir, err := system.GetUserDataDirPath()
if err != nil {
return nil, fmt.Errorf("could not get user data directory: %w", err)
}
sqliteDBFilePath := path.Join(userDataDir, "yj.db")
logger.Debug("opening sqlite database", "filepath", sqliteDBFilePath)
db, err := sql.Open("sqlite", sqliteDBFilePath+"?_busy_timeout=5000&_journal_mode=WAL")
if err != nil {
return nil, fmt.Errorf("could not connect to sqlite database: %w", err)
}
db.SetMaxOpenConns(1) // SQLite only supports one writer at a time
// Execute SQL files from the embedded schemas directory
logger.Debug("reading sql schema files from embedded directory")
dirEntries, err := schemas.ReadDir("sql/schemas")
if err != nil {
return nil, fmt.Errorf("could not read schemas directory: %w", err)
}
logger.Debug("executing all sql schema files")
for _, dirEntry := range dirEntries {
if !dirEntry.IsDir() {
filePath := path.Join("sql/schemas", dirEntry.Name())
sqlContent, err := fs.ReadFile(schemas, filePath)
if err != nil {
return nil, fmt.Errorf("could not read file %s: %w", filePath, err)
}
logger.Debug(
"executing sql schema file",
"filepath",
filePath,
"sql",
string(sqlContent),
)
_, err = db.ExecContext(dbCtx, string(sqlContent)) // Execute the SQL
if err != nil {
return nil, fmt.Errorf("error executing sql from file %s: %w", filePath, err)
}
}
}
// Get generated queries
queries := sqlcgen.New(db)
return &DB{
db: db,
Ctx: dbCtx,
Queries: queries,
logger: logger,
}, err
}