This repository has been archived by the owner on Apr 7, 2024. It is now read-only.
forked from pressly/goose
/
create.go
127 lines (105 loc) · 2.84 KB
/
create.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
package goose
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"text/template"
"time"
"github.com/pkg/errors"
)
type tmplVars struct {
Version string
CamelName string
Values map[string]string
}
var (
sequential = false
)
// SetSequential set whether to use sequential versioning instead of timestamp based versioning
func SetSequential(s bool) {
sequential = s
}
// Create writes a new blank migration file.
func CreateWithTemplate(db *sql.DB, dir string, tmpl *template.Template, name, migrationType string, values map[string]string) error {
var version string
if sequential {
// always use DirFS here because it's modifying operation
migrations, err := collectMigrationsFS(osFS{}, dir, minVersion, maxVersion)
if err != nil {
return err
}
vMigrations, err := migrations.versioned()
if err != nil {
return err
}
if last, err := vMigrations.Last(); err == nil {
version = fmt.Sprintf(seqVersionTemplate, last.Version+1)
} else {
version = fmt.Sprintf(seqVersionTemplate, int64(1))
}
} else {
version = time.Now().Format(timestampFormat)
}
filename := fmt.Sprintf("%v_%v.%v", version, snakeCase(name), migrationType)
if tmpl == nil {
if migrationType == "go" {
tmpl = goSQLMigrationTemplate
} else {
tmpl = sqlMigrationTemplate
}
}
path := filepath.Join(dir, filename)
if _, err := os.Stat(path); !os.IsNotExist(err) {
return errors.Wrap(err, "failed to create migration file")
}
f, err := os.Create(path)
if err != nil {
return errors.Wrap(err, "failed to create migration file")
}
defer f.Close()
vars := tmplVars{
Version: version,
CamelName: camelCase(name),
Values: values,
}
if err := tmpl.Execute(f, vars); err != nil {
return errors.Wrap(err, "failed to execute tmpl")
}
log.Printf("Created new file: %s\n", f.Name())
return nil
}
// Create writes a new blank migration file.
func Create(db *sql.DB, dir, name, migrationType string, values map[string]string, opts ...OptionsFunc) error {
option := &options{}
for _, f := range opts {
f(option)
}
return CreateWithTemplate(db, dir, option.template, name, migrationType, values)
}
var sqlMigrationTemplate = template.Must(template.New("goose.sql-migration").Parse(`-- +goose Up
-- +goose StatementBegin
SELECT 'up SQL query';
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
SELECT 'down SQL query';
-- +goose StatementEnd
`))
var goSQLMigrationTemplate = template.Must(template.New("goose.go-migration").Parse(`package migrations
import (
"database/sql"
"github.com/WinnerSoftLab/goose/v3"
)
func init() {
goose.AddMigration(up{{.CamelName}}, down{{.CamelName}})
}
func up{{.CamelName}}(tx *sql.Tx) error {
// This code is executed when the migration is applied.
return nil
}
func down{{.CamelName}}(tx *sql.Tx) error {
// This code is executed when the migration is rolled back.
return nil
}
`))