-
Notifications
You must be signed in to change notification settings - Fork 0
/
upgrade.go
70 lines (61 loc) · 1.99 KB
/
upgrade.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
package store
import (
"context"
"fmt"
"io"
"log"
"os"
)
// GetCurrentSchemaVersion gets the current version of the database schema. A completely fresh
// database will have version of 0.
func GetCurrentSchemaVersion(ctx context.Context) int {
row := pool.QueryRow(ctx, "SELECT version FROM schema_version")
var version int
if err := row.Scan(&version); err != nil {
// The error could be anything, but we'll assume it's just that the table doesn't exist. That
// is, we need to start from scratch and re-create everything.
return 0
}
return version
}
// UpgradeSchema upgrades the current database schema to the latest version, starting from the
// given current version.
func UpgradeSchema(ctx context.Context, currentVersion int) error {
for {
script, err := loadSchemaUpgradeScript(ctx, currentVersion+1)
if err != nil {
if os.IsNotExist(err) {
log.Printf("Schema up-to-date at version %d", currentVersion)
_, err := pool.Exec(ctx, "UPDATE schema_version SET version=$1", currentVersion)
return err
}
return fmt.Errorf("error loading schema script: %w", err)
}
_, err = pool.Exec(ctx, script)
if err != nil {
return fmt.Errorf("error executing command: %w", err)
}
currentVersion += 1
}
}
// loadSchemaUpgradeScript loads the script to upgrade us to the given version. If the script does
// not exist, returns an error that you can check for with os.IsNotExist -- any other errors are
// real.
func loadSchemaUpgradeScript(ctx context.Context, version int) (string, error) {
filename := fmt.Sprintf("store/schema/schema-%03d.sql", version)
f, err := os.Open(filename)
if err != nil {
if !os.IsNotExist(err) {
// We'll return the error anyway, but if it's something other than a not exists error, then
// it's probably bad...
log.Printf("Got something other than NotExist: %s", err.Error())
}
return "", err
}
bytes, err := io.ReadAll(f)
if err != nil {
return "", err
}
log.Printf("Loaded upgrade script %s", filename)
return string(bytes), nil
}