Make Migrate3 idempotent against partial application
If Migrate3 has already applied its schema changes but failed to bump user_version (e.g. process crashed between ALTER and SetMigrationVersion), the next run currently hits a duplicate column error because ALTER TABLE ADD COLUMN is not idempotent in SQLite. Detect the recovery case by checking for the presence of the v3 target columns and the absence of the dropped Code column, and just record the migration version when found.
This commit is contained in:
@@ -237,9 +237,33 @@ internal class MessageStore : IDisposable
|
||||
SetMigrationVersion(2);
|
||||
}
|
||||
|
||||
private bool ColumnExists(string table, string column)
|
||||
{
|
||||
using var cmd = Connection.CreateCommand();
|
||||
cmd.CommandText = $"PRAGMA table_info({table});";
|
||||
using var reader = cmd.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.GetString(1) == column)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void Migrate3()
|
||||
{
|
||||
Plugin.Log.Information("Running migration 3: Fix log kinds to fit the new format");
|
||||
|
||||
// Recovery for partially-applied Migrate3: if the schema is already
|
||||
// in its target shape (new columns exist, old Code column gone) but
|
||||
// user_version was never bumped, just record the version and exit.
|
||||
if (ColumnExists("messages", "ChatType") && !ColumnExists("messages", "Code"))
|
||||
{
|
||||
Plugin.Log.Information("Migration 3: schema already migrated, only bumping user_version");
|
||||
SetMigrationVersion(3);
|
||||
return;
|
||||
}
|
||||
|
||||
Connection.Execute(@"
|
||||
-- Migration 3: Fix log kinds to fit the new format
|
||||
-- Add new ChatType, SourceKind, TargetKind (byte), SortCodeV2
|
||||
|
||||
Reference in New Issue
Block a user