package store import ( "database/sql" _ "embed" "fmt" "github.com/syonad/clonepack/config" _ "modernc.org/sqlite" ) //go:embed migrations/000001_init.up.sql var migration001 string //go:embed migrations/000002_clone_jobs.up.sql var migration002 string //go:embed migrations/000003_sync.up.sql var migration003 string //go:embed migrations/000004_snapshot_packages.up.sql var migration004 string //go:embed migrations/000005_blocked_packages.up.sql var migration005 string //go:embed migrations/000006_blocked_packages_name.up.sql var migration006 string func Open(cfg config.DBConfig) (*sql.DB, error) { db, err := sql.Open("sqlite", cfg.Path) if err != nil { return nil, fmt.Errorf("open db: %w", err) } if _, err := db.Exec("PRAGMA journal_mode=WAL"); err != nil { return nil, fmt.Errorf("set WAL mode: %w", err) } if _, err := db.Exec("PRAGMA foreign_keys=ON"); err != nil { return nil, fmt.Errorf("enable foreign keys: %w", err) } if err := runMigrations(db); err != nil { return nil, fmt.Errorf("migrations: %w", err) } return db, nil } func runMigrations(db *sql.DB) error { _, err := db.Exec(`CREATE TABLE IF NOT EXISTS schema_migrations ( version INTEGER PRIMARY KEY, applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP )`) if err != nil { return err } migrations := []struct { version int sql string }{ {1, migration001}, {2, migration002}, {3, migration003}, {4, migration004}, {5, migration005}, {6, migration006}, } for _, m := range migrations { var count int row := db.QueryRow("SELECT COUNT(*) FROM schema_migrations WHERE version = ?", m.version) if err := row.Scan(&count); err != nil { return err } if count > 0 { continue } if _, err := db.Exec(m.sql); err != nil { return fmt.Errorf("migration %d: %w", m.version, err) } if _, err := db.Exec("INSERT INTO schema_migrations (version) VALUES (?)", m.version); err != nil { return err } } return nil }