db: fix migration runner - proper schema_migrations checksum handling for existing DBs

- Check if checksum column exists before querying it
- For old DBs (no checksum col): use COUNT(*) to check if migration applied
- For new DBs (has checksum col): use checksum value
- All migrations run in a single transaction
This commit is contained in:
2026-07-19 22:20:55 -04:00
parent dfb667e340
commit 5cb21ddceb
+39 -28
View File
@@ -71,11 +71,32 @@ func (db *DB) runMigrationsInternal(mfs embedFS, migrationsRoot string) error {
return fmt.Errorf("creating schema_migrations table: %w", err)
}
hasChecksumCol := false
if rows, err := db.Query("PRAGMA table_info(schema_migrations)"); err == nil {
for rows.Next() {
var cid int
var cname string
rows.Scan(&cid, &cname, new(string), new(int), new(interface{}), new(int))
if cname == "checksum" {
hasChecksumCol = true
}
}
rows.Close()
}
for _, name := range names {
var storedChecksum string
row := db.QueryRow("SELECT checksum FROM schema_migrations WHERE version = ?", name)
if err := row.Scan(&storedChecksum); err == nil && storedChecksum != "" {
continue
if hasChecksumCol {
var storedChecksum string
row := db.QueryRow("SELECT checksum FROM schema_migrations WHERE version = ?", name)
if err := row.Scan(&storedChecksum); err == nil && storedChecksum != "" {
continue
}
} else {
var count int
row := db.QueryRow("SELECT COUNT(*) FROM schema_migrations WHERE version = ?", name)
if err := row.Scan(&count); err == nil && count > 0 {
continue
}
}
data, err := mfs.ReadFile(filepath.Join(migrationsRoot, name))
@@ -96,32 +117,22 @@ func (db *DB) runMigrationsInternal(mfs embedFS, migrationsRoot string) error {
return fmt.Errorf("applying migration %s: %w", name, err)
}
var insertSQL string
var insertArgs []interface{}
insertArgs = append(insertArgs, name)
hasChecksum := false
rows, _ := tx.Query("PRAGMA table_info(schema_migrations)")
if rows != nil {
for rows.Next() {
var cid int
var cname string
rows.Scan(&cid, &cname, new(string), new(int), new(interface{}), new(int))
if cname == "checksum" {
hasChecksum = true
}
if hasChecksumCol {
if _, err := tx.Exec(
"INSERT INTO schema_migrations (version, checksum) VALUES (?, ?)",
name, checksumHex,
); err != nil {
tx.Rollback()
return fmt.Errorf("recording migration %s: %w", name, err)
}
rows.Close()
}
if hasChecksum {
insertSQL = "INSERT INTO schema_migrations (version, checksum) VALUES (?, ?)"
insertArgs = append(insertArgs, checksumHex)
} else {
insertSQL = "INSERT INTO schema_migrations (version) VALUES (?)"
}
if _, err := tx.Exec(insertSQL, insertArgs...); err != nil {
tx.Rollback()
return fmt.Errorf("recording migration %s: %w", name, err)
if _, err := tx.Exec(
"INSERT INTO schema_migrations (version) VALUES (?)",
name,
); err != nil {
tx.Rollback()
return fmt.Errorf("recording migration %s: %w", name, err)
}
}
if err := tx.Commit(); err != nil {