Unverified Commit 07e82c3f authored by boojack's avatar boojack Committed by GitHub

fix: schema migrate (#1846)

* fix: schema migrate

* chore: update
parent b34aded3
...@@ -50,64 +50,70 @@ func (db *DB) Open(ctx context.Context) (err error) { ...@@ -50,64 +50,70 @@ func (db *DB) Open(ctx context.Context) (err error) {
db.DBInstance = sqliteDB db.DBInstance = sqliteDB
if db.profile.Mode == "prod" { if db.profile.Mode == "prod" {
// If db file not exists, we should migrate the database. _, err := os.Stat(db.profile.DSN)
if _, err := os.Stat(db.profile.DSN); errors.Is(err, os.ErrNotExist) {
if err := db.applyLatestSchema(ctx); err != nil {
return fmt.Errorf("failed to apply latest schema: %w", err)
}
}
currentVersion := version.GetCurrentVersion(db.profile.Mode)
migrationHistoryList, err := db.FindMigrationHistoryList(ctx, &MigrationHistoryFind{})
if err != nil { if err != nil {
return fmt.Errorf("failed to find migration history, err: %w", err) // If db file not exists, we should create a new one with latest schema.
} if errors.Is(err, os.ErrNotExist) {
if len(migrationHistoryList) == 0 { if err := db.applyLatestSchema(ctx); err != nil {
_, err := db.UpsertMigrationHistory(ctx, &MigrationHistoryUpsert{ return fmt.Errorf("failed to apply latest schema, err: %w", err)
Version: currentVersion, }
}) } else {
return fmt.Errorf("failed to get db file stat, err: %w", err)
}
} else {
// If db file exists, we should check if we need to migrate the database.
currentVersion := version.GetCurrentVersion(db.profile.Mode)
migrationHistoryList, err := db.FindMigrationHistoryList(ctx, &MigrationHistoryFind{})
if err != nil { if err != nil {
return fmt.Errorf("failed to upsert migration history, err: %w", err) return fmt.Errorf("failed to find migration history, err: %w", err)
}
if len(migrationHistoryList) == 0 {
_, err := db.UpsertMigrationHistory(ctx, &MigrationHistoryUpsert{
Version: currentVersion,
})
if err != nil {
return fmt.Errorf("failed to upsert migration history, err: %w", err)
}
return nil
} }
return nil
}
migrationHistoryVersionList := []string{} migrationHistoryVersionList := []string{}
for _, migrationHistory := range migrationHistoryList { for _, migrationHistory := range migrationHistoryList {
migrationHistoryVersionList = append(migrationHistoryVersionList, migrationHistory.Version) migrationHistoryVersionList = append(migrationHistoryVersionList, migrationHistory.Version)
} }
sort.Sort(version.SortVersion(migrationHistoryVersionList)) sort.Sort(version.SortVersion(migrationHistoryVersionList))
latestMigrationHistoryVersion := migrationHistoryVersionList[len(migrationHistoryVersionList)-1] latestMigrationHistoryVersion := migrationHistoryVersionList[len(migrationHistoryVersionList)-1]
if version.IsVersionGreaterThan(version.GetSchemaVersion(currentVersion), latestMigrationHistoryVersion) { if version.IsVersionGreaterThan(version.GetSchemaVersion(currentVersion), latestMigrationHistoryVersion) {
minorVersionList := getMinorVersionList() minorVersionList := getMinorVersionList()
// backup the raw database file before migration // backup the raw database file before migration
rawBytes, err := os.ReadFile(db.profile.DSN) rawBytes, err := os.ReadFile(db.profile.DSN)
if err != nil { if err != nil {
return fmt.Errorf("failed to read raw database file, err: %w", err) return fmt.Errorf("failed to read raw database file, err: %w", err)
} }
backupDBFilePath := fmt.Sprintf("%s/memos_%s_%d_backup.db", db.profile.Data, db.profile.Version, time.Now().Unix()) backupDBFilePath := fmt.Sprintf("%s/memos_%s_%d_backup.db", db.profile.Data, db.profile.Version, time.Now().Unix())
if err := os.WriteFile(backupDBFilePath, rawBytes, 0644); err != nil { if err := os.WriteFile(backupDBFilePath, rawBytes, 0644); err != nil {
return fmt.Errorf("failed to write raw database file, err: %w", err) return fmt.Errorf("failed to write raw database file, err: %w", err)
} }
println("succeed to copy a backup database file") println("succeed to copy a backup database file")
println("start migrate") println("start migrate")
for _, minorVersion := range minorVersionList { for _, minorVersion := range minorVersionList {
normalizedVersion := minorVersion + ".0" normalizedVersion := minorVersion + ".0"
if version.IsVersionGreaterThan(normalizedVersion, latestMigrationHistoryVersion) && version.IsVersionGreaterOrEqualThan(currentVersion, normalizedVersion) { if version.IsVersionGreaterThan(normalizedVersion, latestMigrationHistoryVersion) && version.IsVersionGreaterOrEqualThan(currentVersion, normalizedVersion) {
println("applying migration for", normalizedVersion) println("applying migration for", normalizedVersion)
if err := db.applyMigrationForMinorVersion(ctx, minorVersion); err != nil { if err := db.applyMigrationForMinorVersion(ctx, minorVersion); err != nil {
return fmt.Errorf("failed to apply minor version migration: %w", err) return fmt.Errorf("failed to apply minor version migration: %w", err)
}
} }
} }
} println("end migrate")
println("end migrate")
// remove the created backup db file after migrate succeed // remove the created backup db file after migrate succeed
if err := os.Remove(backupDBFilePath); err != nil { if err := os.Remove(backupDBFilePath); err != nil {
println(fmt.Sprintf("Failed to remove temp database file, err %v", err)) println(fmt.Sprintf("Failed to remove temp database file, err %v", err))
}
} }
} }
} else { } else {
......
...@@ -67,7 +67,7 @@ func findMigrationHistoryList(ctx context.Context, tx *sql.Tx, find *MigrationHi ...@@ -67,7 +67,7 @@ func findMigrationHistoryList(ctx context.Context, tx *sql.Tx, find *MigrationHi
FROM FROM
migration_history migration_history
WHERE ` + strings.Join(where, " AND ") + ` WHERE ` + strings.Join(where, " AND ") + `
ORDER BY version DESC ORDER BY created_ts DESC
` `
rows, err := tx.QueryContext(ctx, query, args...) rows, err := tx.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment