forked from gsamokovarov/gloat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
store.go
166 lines (145 loc) · 4.31 KB
/
store.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package gloat
// Store is an interface representing a place where the applied migrations are
// recorded.
type Store interface {
Source
Insert(*Migration, SQLExecer) error
Remove(*Migration, SQLExecer) error
}
// DatabaseStore is a Store that keeps the applied migrations in a database
// table called schema_migrations. The table is automatically created if it
// does not exist.
type DatabaseStore struct {
db SQLTransactor
createTableStatement string
createIndexStatement string
insertMigrationStatement string
removeMigrationStatement string
selectAllMigrationsStatement string
}
// Insert records a migration version into the schema_migrations table.
func (s *DatabaseStore) Insert(migration *Migration, execer SQLExecer) error {
if execer == nil {
execer = s.db
}
if err := s.ensureSchemaTableExists(); err != nil {
return err
}
_, err := execer.Exec(s.insertMigrationStatement, migration.Version, migration.AppliedAt)
return err
}
// Remove removes a migration version from the schema_migrations table.
func (s *DatabaseStore) Remove(migration *Migration, execer SQLExecer) error {
if execer == nil {
execer = s.db
}
if err := s.ensureSchemaTableExists(); err != nil {
return err
}
_, err := execer.Exec(s.removeMigrationStatement, migration.Version)
return err
}
// Collect builds a slice of migrations with the versions of the recorded
// applied migrations.
func (s *DatabaseStore) Collect() (migrations Migrations, err error) {
if err = s.ensureSchemaTableExists(); err != nil {
return
}
rows, err := s.db.Query(s.selectAllMigrationsStatement)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
migration := &Migration{}
if err = rows.Scan(&migration.Version, &migration.AppliedAt); err != nil {
return
}
migrations = append(migrations, migration)
}
return
}
func (s *DatabaseStore) ensureSchemaTableExists() error {
if _, err := s.db.Exec(s.createTableStatement); err != nil {
return err
}
if _, err := s.db.Exec(s.createIndexStatement); err != nil {
return err
}
return nil
}
// NewPostgreSQLStore creates a Store for PostgreSQL.
func NewPostgreSQLStore(db SQLTransactor) Store {
return &DatabaseStore{
db: db,
createTableStatement: `
CREATE TABLE IF NOT EXISTS schema_migrations (
version BIGINT PRIMARY KEY NOT NULL,
applied_at timestamp without time zone default (now() at time zone 'utc')
)`,
createIndexStatement: `
CREATE INDEX IF NOT EXISTS schema_migrations_applied_at
ON schema_migrations (applied_at)
`,
insertMigrationStatement: `
INSERT INTO schema_migrations (version, applied_at)
VALUES ($1, $2)`,
removeMigrationStatement: `
DELETE FROM schema_migrations
WHERE version=$1`,
selectAllMigrationsStatement: `
SELECT version, applied_at
FROM schema_migrations
ORDER BY applied_at DESC, version DESC`,
}
}
// NewMySQLStore creates a Store for MySQL.
func NewMySQLStore(db SQLTransactor) Store {
return &DatabaseStore{
db: db,
createTableStatement: `
CREATE TABLE IF NOT EXISTS schema_migrations (
version BIGINT PRIMARY KEY NOT NULL,
applied_at TIMESTAMP DEFAULT UTC_TIMESTAMP
)`,
createIndexStatement: `
CREATE INDEX IF NOT EXISTS schema_migrations_applied_at
ON schema_migrations (applied_at)
`,
insertMigrationStatement: `
INSERT INTO schema_migrations (version, applied_at)
VALUES (?, ?)`,
removeMigrationStatement: `
DELETE FROM schema_migrations
WHERE version=?`,
selectAllMigrationsStatement: `
SELECT version, applied_at
FROM schema_migrations
ORDER BY applied_at DESC, version DESC`,
}
}
// NewSQLite3Store creates a Store for SQLite3.
func NewSQLite3Store(db SQLTransactor) Store {
return &DatabaseStore{
db: db,
createTableStatement: `
CREATE TABLE IF NOT EXISTS schema_migrations (
version BIGINT PRIMARY KEY NOT NULL
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`,
insertMigrationStatement: `
INSERT INTO schema_migrations (version, applied_at)
VALUES (?, ?)`,
createIndexStatement: `
CREATE INDEX IF NOT EXISTS schema_migrations_applied_at
ON schema_migrations (applied_at)
`,
removeMigrationStatement: `
DELETE FROM schema_migrations
WHERE version=?`,
selectAllMigrationsStatement: `
SELECT version, applied_at
FROM schema_migrations
ORDER BY applied_at DESC, version DESC`,
}
}