package main import ( "database/sql" "embed" "fmt" "io/fs" "log" "path/filepath" ) const ( migrationDir = `sql/migrations` migrationFilePattern = `%04d.sqlite3` ) var migrations []string //go:embed sql/migrations/*.sqlite3 var migrationsFS embed.FS func init() { readMigrations() } func readMigrations() { i := 1 _ = fs.WalkDir(migrationsFS, migrationDir, func(path string, d fs.DirEntry, err error) error { if !d.IsDir() { expected := fmt.Sprintf(migrationFilePattern, i) if filepath.Base(path) == expected { data, err := fs.ReadFile(migrationsFS, path) if err != nil { log.Fatalf("Could not read migration: %v", err) } migrations = append(migrations, string(data)) i += 1 } } return nil }) } func Transaction(db *sql.DB, f func(*sql.Tx) error) error { tx, err := db.Begin() if err != nil { return err } defer tx.Rollback() err = f(tx) if err != nil { return err } return tx.Commit() } func Migrate(db *sql.DB, index int) error { return Transaction(db, func(tx *sql.Tx) error { _, err := tx.Exec(migrations[index]) return err }) }