package migrations import ( "context" "database/sql" "fmt" "log/slog" "path" "queryorchestration/internal/serviceconfig" "queryorchestration/internal/serviceconfig/database" "github.com/golang-migrate/migrate/v4" _ "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file" _ "github.com/lib/pq" ) func createDB(cfg database.ConfigProvider) error { connStr := fmt.Sprintf("%s?%s", cfg.GetDBBaseURI(), cfg.GetDBOptsString()) db, err := sql.Open(cfg.GetDBDriver(), connStr) if err != nil { return fmt.Errorf("error opening database: %v", err) } err = db.Ping() if err != nil { return fmt.Errorf("error pinging database: %v", err) } rs, err := db.Query(fmt.Sprintf("SELECT 'CREATE DATABASE %s' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '%s')", cfg.GetDBName(), cfg.GetDBName())) if err != nil { return fmt.Errorf("error creating database: %v", err) } if rs.Next() { slog.Info("database created", "name", cfg.GetDBName()) } else { slog.Info("database already exists", "name", cfg.GetDBName()) } return nil } func Run(ctx context.Context, cfg serviceconfig.ConfigProvider) error { err := createDB(cfg) if err != nil { return err } migPath := "file://" + path.Join(cfg.GetBasePath(), "database/migrations") m, err := migrate.New( migPath, cfg.GetDBURI(), ) if err != nil { return fmt.Errorf("failed to create migrate instance: %v", err) } err = m.Up() if err == migrate.ErrNoChange { slog.Info("No migration changes required") } else if err != nil { return fmt.Errorf("failed to apply migrations: %v", err) } else { slog.Info("Migrations applied successfully!") } return nil }