package database import ( "context" "database/sql" "embed" "errors" "fmt" "log/slog" "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/golang-migrate/migrate/v4/source/iofs" _ "github.com/lib/pq" ) func createDB(ctx context.Context, cfg database.ConfigProvider) error { slog.Debug("creating connection to admin database", "uri", cfg.GetDBAdminDBURI()) db, err := sql.Open(cfg.GetDBDriver(), cfg.GetDBAdminDBURI()) if err != nil { return fmt.Errorf("error opening admin database: %w", err) } slog.Debug("pinging admin database", "uri", cfg.GetDBAdminDBURI()) err = db.PingContext(ctx) if err != nil { return fmt.Errorf("error pinging admin database: %w", err) } slog.Debug("creating admin database", "uri", cfg.GetDBAdminDBURI()) _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", cfg.GetDBName())) if err != nil { slog.Info("database not created", "name", cfg.GetDBName(), "error", err.Error()) } else { slog.Info("database created", "name", cfg.GetDBName()) } slog.Debug("creating connection to database", "uri", cfg.GetDBAdminDBURI()) db, err = sql.Open(cfg.GetDBDriver(), cfg.GetDBURI()) if err != nil { return fmt.Errorf("error opening database: %w", err) } slog.Debug("pinging database", "uri", cfg.GetDBAdminDBURI()) err = db.PingContext(ctx) if err != nil { return fmt.Errorf("error pinging database: %w", err) } return nil } //go:embed migrations/*.up.sql var migrations embed.FS func RunMigrations(ctx context.Context, cfg database.ConfigProvider) error { err := createDB(ctx, cfg) if err != nil { return err } source, err := iofs.New(migrations, "migrations") if err != nil { return err } m, err := migrate.NewWithSourceInstance("iofs", source, cfg.GetDBURI()) if err != nil { return fmt.Errorf("failed to create migrate instance: %w", err) } err = m.Up() if errors.Is(err, migrate.ErrNoChange) { slog.Info("No migration changes required") } else if err != nil { return fmt.Errorf("failed to apply migrations: %w", err) } else { slog.Info("Migrations applied successfully!") } return nil }