Change schema_migrations version from TEXT to INTEGER
All checks were successful
check / check (push) Successful in 1m42s

This commit is contained in:
clawbot
2026-03-19 23:07:03 -07:00
parent 2074571a87
commit 49398c1f0f
3 changed files with 41 additions and 35 deletions

View File

@@ -9,6 +9,7 @@ import (
"log/slog"
"path/filepath"
"sort"
"strconv"
"strings"
"go.uber.org/fx"
@@ -23,7 +24,7 @@ var schemaFS embed.FS
// bootstrapVersion is the migration that creates the schema_migrations
// table itself. It is applied before the normal migration loop.
const bootstrapVersion = "000"
const bootstrapVersion = 0
// Params defines dependencies for Database.
type Params struct {
@@ -42,35 +43,40 @@ type Database struct {
// ParseMigrationVersion extracts the numeric version prefix from a migration
// filename. Filenames must follow the pattern "<version>.sql" or
// "<version>_<description>.sql", where version is a zero-padded numeric
// string (e.g. "001", "002"). Returns the version string and an error if
// the filename does not match the expected pattern.
func ParseMigrationVersion(filename string) (string, error) {
// string (e.g. "001", "002"). Returns the version as an integer and an
// error if the filename does not match the expected pattern.
func ParseMigrationVersion(filename string) (int, error) {
name := strings.TrimSuffix(filename, filepath.Ext(filename))
if name == "" {
return "", fmt.Errorf("invalid migration filename %q: empty name", filename)
return 0, fmt.Errorf("invalid migration filename %q: empty name", filename)
}
// Split on underscore to separate version from description.
// If there's no underscore, the entire stem is the version.
version := name
versionStr := name
if idx := strings.IndexByte(name, '_'); idx >= 0 {
version = name[:idx]
versionStr = name[:idx]
}
if version == "" {
return "", fmt.Errorf("invalid migration filename %q: empty version prefix", filename)
if versionStr == "" {
return 0, fmt.Errorf("invalid migration filename %q: empty version prefix", filename)
}
// Validate the version is purely numeric.
for _, ch := range version {
for _, ch := range versionStr {
if ch < '0' || ch > '9' {
return "", fmt.Errorf(
return 0, fmt.Errorf(
"invalid migration filename %q: version %q contains non-numeric character %q",
filename, version, string(ch),
filename, versionStr, string(ch),
)
}
}
version, err := strconv.Atoi(versionStr)
if err != nil {
return 0, fmt.Errorf("invalid migration filename %q: %w", filename, err)
}
return version, nil
}