-
Notifications
You must be signed in to change notification settings - Fork 0
/
migo.go
135 lines (112 loc) · 3.1 KB
/
migo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package migo
import (
"errors"
"fmt"
"log"
"time"
"github.com/CloudInn/gormigrate/v2"
"github.com/fatih/color"
"gorm.io/gorm"
)
type Migrations []*gormigrate.Migration
type gormGooseData struct {
lastAppliedMigrationID string
}
type gormMigration struct {
ID int
VersionID int
TStamp time.Time
IsApplied bool
}
var DefaultOptions *Options = &Options{
Options: *gormigrate.DefaultOptions,
}
type Options struct {
gormigrate.Options
PgSchema string
}
func (o Options) WithPgSchema(pgschema string) *Options {
d := DefaultOptions
d.PgSchema = pgschema
return d
}
var dbClient *gorm.DB
var schemaname string
var (
errNoGormGooseMigrationTable error = errors.New("no gorm goose table found")
errNoAppliedMigrations error = errors.New("no applied gorm-goose migrations")
)
func Run(db *gorm.DB, migrations Migrations, command string, options *Options) error {
schemaname = options.PgSchema
if db != nil {
dbClient = db
} else {
log.Fatalln("dbClient is nil")
}
options.TableName = fmt.Sprintf("%s.%s", options.PgSchema, options.TableName)
m := gormigrate.New(db, &options.Options, migrations)
switch command {
case "up":
ggd, err := getGormGooseData()
if err != nil {
switch err {
case errNoGormGooseMigrationTable:
if err := m.Migrate(); err != nil {
log.Fatalf("Could not migrate: %v", err)
}
case errNoAppliedMigrations:
if err := m.Migrate(); err != nil {
log.Fatalf("Could not migrate: %v", err)
}
default:
return err
}
} else {
if err := m.FakeMigrateTo(ggd.lastAppliedMigrationID); err != nil {
log.Fatalf("Could not migrate: %v", err)
}
if err := m.Migrate(); err != nil {
log.Fatalf("Could not migrate: %v", err)
}
}
case "down":
if err := m.RollbackLast(); err != nil {
log.Fatalf("Could not rollback: %v", err)
}
default:
return errors.New("invalid -migrate subcommand (should be neither up, down or gen)")
}
color.Green("\n** Migration run successfully **")
return nil
}
func NewID() string {
return time.Now().Format("20060102150405")
}
func getGormGooseData() (gormGooseData, error) {
ggd := gormGooseData{}
var err error
if !gormGooseMigrationTableExist() {
return gormGooseData{}, errNoGormGooseMigrationTable
}
ggd.lastAppliedMigrationID, err = getLastGormGooseAppliedMigration()
if err != nil {
return gormGooseData{}, err
}
return ggd, err
}
func gormGooseMigrationTableExist() bool {
exists := dbClient.Migrator().HasTable(fmt.Sprintf("%s.%s", schemaname, "migration_records"))
fmt.Println("migration_records exists", exists)
return exists
}
func getLastGormGooseAppliedMigration() (string, error) {
gm := gormMigration{}
result := dbClient.Raw(fmt.Sprintf("SELECT * FROM %s.migration_records WHERE id IN (SELECT MAX(id) FROM %s.migration_records GROUP BY version_id) AND is_applied = TRUE ORDER BY version_id DESC LIMIT 1;", schemaname, schemaname)).Scan(&gm)
if errors.Is(result.Error, gorm.ErrRecordNotFound) || result.RowsAffected == 0 {
return "", errNoAppliedMigrations
}
if result.Error != nil {
return "", result.Error
}
return fmt.Sprint(gm.VersionID), result.Error
}