package migrate import ( "database/sql" "embed" "fmt" "log" "log/slog" _ "github.com/mattn/go-sqlite3" ) //go:embed migrations/*.sql var migrations embed.FS type Migration struct { Version int Name string } func Migrate(db *sql.DB) { slog.Info("Running migrations...") migrationTableSql := ` CREATE TABLE IF NOT EXISTS migrations( version SERIAL PRIMARY KEY, name VARCHAR(50) );` _, err := db.Exec(migrationTableSql) if err != nil { log.Fatal(err) } files, err := migrations.ReadDir("migrations") if err != nil { log.Fatal("Failed to read migrations directory") } for _, file := range files { var migration Migration row := db.QueryRow("SELECT * FROM migrations WHERE name = $1;", file.Name()) err = row.Scan(&migration.Version, &migration.Name) if err == sql.ErrNoRows { slog.Info(fmt.Sprintf("Running migration: %s", file.Name())) migrationSql, err := migrations.ReadFile(fmt.Sprintf("migrations/%s", file.Name())) if err != nil { log.Fatal(err) } _, err = db.Exec(string(migrationSql)) if err != nil { log.Fatal(err) } _, err = db.Exec("INSERT INTO migrations(name) VALUES($1);", file.Name()) if err != nil { log.Fatal(err) } } } slog.Info("Migrations completed") }