From 07e82c3f4a0a85f33906e84f93c9a1aaf6a37544 Mon Sep 17 00:00:00 2001 From: boojack Date: Tue, 20 Jun 2023 12:18:04 +0800 Subject: [PATCH] fix: schema migrate (#1846) * fix: schema migrate * chore: update --- store/db/db.go | 106 ++++++++++++++++++---------------- store/db/migration_history.go | 2 +- 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/store/db/db.go b/store/db/db.go index 02034a3d..3ec38430 100644 --- a/store/db/db.go +++ b/store/db/db.go @@ -50,64 +50,70 @@ func (db *DB) Open(ctx context.Context) (err error) { db.DBInstance = sqliteDB if db.profile.Mode == "prod" { - // If db file not exists, we should migrate the database. - 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{}) + _, err := os.Stat(db.profile.DSN) if err != nil { - return fmt.Errorf("failed to find migration history, err: %w", err) - } - if len(migrationHistoryList) == 0 { - _, err := db.UpsertMigrationHistory(ctx, &MigrationHistoryUpsert{ - Version: currentVersion, - }) + // If db file not exists, we should create a new one with latest schema. + if errors.Is(err, os.ErrNotExist) { + if err := db.applyLatestSchema(ctx); err != nil { + return fmt.Errorf("failed to apply latest schema, err: %w", err) + } + } 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 { - return fmt.Errorf("failed to upsert migration history, err: %w", err) + return fmt.Errorf("failed to find migration history, err: %w", err) } - return nil - } - - migrationHistoryVersionList := []string{} - for _, migrationHistory := range migrationHistoryList { - migrationHistoryVersionList = append(migrationHistoryVersionList, migrationHistory.Version) - } - sort.Sort(version.SortVersion(migrationHistoryVersionList)) - latestMigrationHistoryVersion := migrationHistoryVersionList[len(migrationHistoryVersionList)-1] - - if version.IsVersionGreaterThan(version.GetSchemaVersion(currentVersion), latestMigrationHistoryVersion) { - minorVersionList := getMinorVersionList() - - // backup the raw database file before migration - rawBytes, err := os.ReadFile(db.profile.DSN) - if err != nil { - return fmt.Errorf("failed to read raw database file, 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 } - 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 { - return fmt.Errorf("failed to write raw database file, err: %w", err) - } - println("succeed to copy a backup database file") - println("start migrate") - for _, minorVersion := range minorVersionList { - normalizedVersion := minorVersion + ".0" - if version.IsVersionGreaterThan(normalizedVersion, latestMigrationHistoryVersion) && version.IsVersionGreaterOrEqualThan(currentVersion, normalizedVersion) { - println("applying migration for", normalizedVersion) - if err := db.applyMigrationForMinorVersion(ctx, minorVersion); err != nil { - return fmt.Errorf("failed to apply minor version migration: %w", err) + migrationHistoryVersionList := []string{} + for _, migrationHistory := range migrationHistoryList { + migrationHistoryVersionList = append(migrationHistoryVersionList, migrationHistory.Version) + } + sort.Sort(version.SortVersion(migrationHistoryVersionList)) + latestMigrationHistoryVersion := migrationHistoryVersionList[len(migrationHistoryVersionList)-1] + + if version.IsVersionGreaterThan(version.GetSchemaVersion(currentVersion), latestMigrationHistoryVersion) { + minorVersionList := getMinorVersionList() + + // backup the raw database file before migration + rawBytes, err := os.ReadFile(db.profile.DSN) + if err != nil { + 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()) + if err := os.WriteFile(backupDBFilePath, rawBytes, 0644); err != nil { + return fmt.Errorf("failed to write raw database file, err: %w", err) + } + println("succeed to copy a backup database file") + + println("start migrate") + for _, minorVersion := range minorVersionList { + normalizedVersion := minorVersion + ".0" + if version.IsVersionGreaterThan(normalizedVersion, latestMigrationHistoryVersion) && version.IsVersionGreaterOrEqualThan(currentVersion, normalizedVersion) { + println("applying migration for", normalizedVersion) + if err := db.applyMigrationForMinorVersion(ctx, minorVersion); err != nil { + 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 - if err := os.Remove(backupDBFilePath); err != nil { - println(fmt.Sprintf("Failed to remove temp database file, err %v", err)) + // remove the created backup db file after migrate succeed + if err := os.Remove(backupDBFilePath); err != nil { + println(fmt.Sprintf("Failed to remove temp database file, err %v", err)) + } } } } else { diff --git a/store/db/migration_history.go b/store/db/migration_history.go index 472bfb53..cbda3445 100644 --- a/store/db/migration_history.go +++ b/store/db/migration_history.go @@ -67,7 +67,7 @@ func findMigrationHistoryList(ctx context.Context, tx *sql.Tx, find *MigrationHi FROM migration_history WHERE ` + strings.Join(where, " AND ") + ` - ORDER BY version DESC + ORDER BY created_ts DESC ` rows, err := tx.QueryContext(ctx, query, args...) if err != nil {