package migrate import ( "context" "embed" "fmt" "log" "log/slog" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) //go:embed migrations/*.sql var migrations embed.FS type Migration struct { Version int Name string } func Migrate(logger *slog.Logger, db *pgxpool.Pool) { logger.Info("Running migrations...") migrationTableSql := ` CREATE TABLE IF NOT EXISTS migrations( version SERIAL PRIMARY KEY, name VARCHAR(50) );` _, err := db.Exec(context.Background(), 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(context.Background(), "SELECT * FROM migrations WHERE name = $1;", file.Name()) err = row.Scan(&migration.Version, &migration.Name) if err == pgx.ErrNoRows { logger.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(context.Background(), string(migrationSql)) if err != nil { log.Fatal(err) } _, err = db.Exec(context.Background(), "INSERT INTO migrations(name) VALUES($1);", file.Name()) if err != nil { log.Fatal(err) } } } logger.Info("Migrations completed") }