niki/pkg/database/postgres/migrator/migrator.go

114 lines
2.3 KiB
Go

package migrator
import (
"database/sql"
"fmt"
"os"
"text/tabwriter"
"git.gocasts.ir/ebhomengo/niki/pkg/database/postgres"
_ "github.com/jackc/pgx/v5/stdlib"
migrate "github.com/rubenv/sql-migrate"
)
type Config struct {
migrationDBName string `koanf:"migration_db_name"`
pathOfMigrations string `koanf:"pathOfMigrations"`
dbConfig postgres.Config
}
type Migrator struct {
cfg Config
dialect string
migrations *migrate.FileMigrationSource
}
func New(cfg Config) *Migrator {
return &Migrator{
cfg: cfg,
dialect: "psx",
migrations: &migrate.FileMigrationSource{Dir: cfg.pathOfMigrations},
}
}
func (m *Migrator) getDsn() string {
return fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable",
m.cfg.dbConfig.Host, m.cfg.dbConfig.User, m.cfg.dbConfig.Password, m.cfg.dbConfig.DbName)
}
func (m *Migrator) Up() {
db, err := sql.Open(m.dialect, m.getDsn())
if err != nil {
panic(fmt.Errorf("can't open postgres db: %v", err))
}
defer db.Close()
if err != nil {
return
}
n, err := migrate.Exec(db, m.dialect, m.migrations, migrate.Up)
if err != nil {
panic(fmt.Errorf("cant apply migrations : %v ", err))
}
fmt.Printf("Applied %d migrations\n", n)
}
func (m *Migrator) Down() {
migrate.SetTable(m.cfg.migrationDBName)
db, err := sql.Open(m.dialect, m.getDsn())
if err != nil {
panic(fmt.Errorf("can't open postgres db: %v", err))
}
defer db.Close()
n, err := migrate.Exec(db, m.dialect, m.migrations, migrate.Down)
if err != nil {
panic(fmt.Errorf("cant rollback migrations : %v ", err))
}
fmt.Printf("Applied %d migrations\n", n)
}
func (m *Migrator) Status() {
migrate.SetTable(m.cfg.migrationDBName)
db, err := sql.Open(m.dialect, m.getDsn())
if err != nil {
panic(fmt.Errorf("can't open postgres db: %v", err))
}
defer db.Close()
migrations, _, err := migrate.PlanMigration(db, m.dialect, m.migrations, migrate.Up, 0)
if err != nil {
panic(fmt.Errorf("can't plan migrations: %v", err))
}
if len(migrations) == 0 {
fmt.Println("✅ No pending migrations.")
return
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "PENDING MIGRATIONS")
fmt.Fprintln(w, "ID\tSTATUS")
for _, migration := range migrations {
fmt.Fprintf(w, "%s\tPending\n", migration.Id)
}
w.Flush()
}