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:
+39
-28
@@ -71,11 +71,32 @@ func (db *DB) runMigrationsInternal(mfs embedFS, migrationsRoot string) error {
|
|||||||
return fmt.Errorf("creating schema_migrations table: %w", err)
|
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 {
|
for _, name := range names {
|
||||||
var storedChecksum string
|
if hasChecksumCol {
|
||||||
row := db.QueryRow("SELECT checksum FROM schema_migrations WHERE version = ?", name)
|
var storedChecksum string
|
||||||
if err := row.Scan(&storedChecksum); err == nil && storedChecksum != "" {
|
row := db.QueryRow("SELECT checksum FROM schema_migrations WHERE version = ?", name)
|
||||||
continue
|
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))
|
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)
|
return fmt.Errorf("applying migration %s: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var insertSQL string
|
if hasChecksumCol {
|
||||||
var insertArgs []interface{}
|
if _, err := tx.Exec(
|
||||||
insertArgs = append(insertArgs, name)
|
"INSERT INTO schema_migrations (version, checksum) VALUES (?, ?)",
|
||||||
hasChecksum := false
|
name, checksumHex,
|
||||||
rows, _ := tx.Query("PRAGMA table_info(schema_migrations)")
|
); err != nil {
|
||||||
if rows != nil {
|
tx.Rollback()
|
||||||
for rows.Next() {
|
return fmt.Errorf("recording migration %s: %w", name, err)
|
||||||
var cid int
|
|
||||||
var cname string
|
|
||||||
rows.Scan(&cid, &cname, new(string), new(int), new(interface{}), new(int))
|
|
||||||
if cname == "checksum" {
|
|
||||||
hasChecksum = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rows.Close()
|
|
||||||
}
|
|
||||||
if hasChecksum {
|
|
||||||
insertSQL = "INSERT INTO schema_migrations (version, checksum) VALUES (?, ?)"
|
|
||||||
insertArgs = append(insertArgs, checksumHex)
|
|
||||||
} else {
|
} else {
|
||||||
insertSQL = "INSERT INTO schema_migrations (version) VALUES (?)"
|
if _, err := tx.Exec(
|
||||||
}
|
"INSERT INTO schema_migrations (version) VALUES (?)",
|
||||||
|
name,
|
||||||
if _, err := tx.Exec(insertSQL, insertArgs...); err != nil {
|
); err != nil {
|
||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return fmt.Errorf("recording migration %s: %w", name, err)
|
return fmt.Errorf("recording migration %s: %w", name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user