-
Notifications
You must be signed in to change notification settings - Fork 9
/
migrate.go
93 lines (82 loc) · 2.12 KB
/
migrate.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
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/spf13/cobra"
"sort"
)
func migrate(cmd *cobra.Command, args []string) {
validate()
connect()
tables := getTables()
makeMigrations(tables, *output)
}
var autoincrementRegExp = regexp.MustCompile(`(?ms) AUTO_INCREMENT=[0-9]*\b`)
// if the folder you are trying to output the migrations in already exists
// archive will move the previous migrations into a timestamped archived folder
// so you can do easy rollbacks
func archive(folder string) {
f, err := os.Stat(folder)
if err != nil || !f.IsDir() {
return
}
archive := fmt.Sprintf("%s_%s", folder, time.Now().Format("2006_01_02_15_04_05"))
if err := os.Rename(folder, archive); err != nil {
log.Fatalf("cannot archive %s folder", folder)
}
}
type statement struct {
tbl string
stmt string
order int
}
type statements []statement
func makeMigrations(tables map[string]string, dst string) {
archive(dst)
os.Mkdir(dst, 0777)
now := time.Now().Unix()
var sts statements
for table, comment := range tables {
// get the create statement
row := database.QueryRow(fmt.Sprintf("SHOW CREATE TABLE `%s`", table))
var tbl, stmt string
row.Scan(&tbl, &stmt)
order := GetOrderFromComment(comment)
st := statement{tbl, stmt, order}
sts = append(sts, st)
}
sort.Slice(sts, func(i, j int) bool {
return sts[i].order < sts[j].order
})
for _, st := range sts {
// Create the up migration
where := filepath.Join(dst, fmt.Sprintf("%d_create_%s.up.sql", now, st.tbl))
up, err := os.Create(where)
if err != nil {
log.Fatal(err)
}
auto := autoincrementRegExp.FindString(st.stmt)
st.stmt = strings.Replace(st.stmt, auto, "", 1)
_, err = up.WriteString(st.stmt + ";")
if err != nil {
log.Fatal(err)
}
// Create the down migration
where = filepath.Join(dst, fmt.Sprintf("%d_create_%s.down.sql", now, st.tbl))
down, err := os.Create(where)
if err != nil {
log.Fatal(err)
}
_, err = down.WriteString(fmt.Sprintf("DROP TABLE IF EXISTS %s;", st.tbl))
if err != nil {
log.Fatal(err)
}
// Ensure the time increments properly
now += 1
}
}