diff options
Diffstat (limited to 'common/db.go')
| -rw-r--r-- | common/db.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/common/db.go b/common/db.go new file mode 100644 index 0000000..76e39a2 --- /dev/null +++ b/common/db.go @@ -0,0 +1,57 @@ +package common + +import ( + "context" + "database/sql" + "embed" + "fmt" + "log/slog" + "path" + "regexp" + "strconv" + "strings" + + "github.com/nyttikord/avl" +) + +var regexpMigration = regexp.MustCompile(`(\d{3})-(.*)\.sql`) + +type migrationData struct { + id uint64 + name string + content string +} + +func Migrate(ctx context.Context, log *slog.Logger, db *sql.DB, migrations embed.FS, dir string) error { + entries, err := migrations.ReadDir(dir) + if err != nil { + return err + } + tree := avl.NewKeySimple[uint64, migrationData]() + for _, entry := range entries { + if strings.HasSuffix(entry.Name(), ".sql") { + log.Debug("reading migration...", "path", dir+"/"+entry.Name()) + subs := regexpMigration.FindStringSubmatch(entry.Name()) + if len(subs) < 3 { + return fmt.Errorf("invalid migration name %s", entry.Name()) + } + id, _ := strconv.ParseUint(subs[1], 10, 16) + b, err := migrations.ReadFile(path.Join(dir, entry.Name())) + if err != nil { + return err + } + tree.Insert(id, migrationData{id, subs[2], string(b)}) + } else { + log.Warn("invalid migration entry, skipping", "path", dir+"/"+entry.Name()) + } + } + for _, mig := range tree.Sort() { + log.Debug("migrating...", "id", mig.id, "name", mig.name) + _, err := db.ExecContext(ctx, mig.content) + if err != nil { + log.Error("migrating", "id", mig.id, "name", mig.name) + return err + } + } + return nil +} |
