From 94064bf9e41a365f3e83e06a52feb6a4c7c936be Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Fri, 1 May 2026 18:19:39 +0200 Subject: [PATCH] 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. --- ChatTwo/MessageStore.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ChatTwo/MessageStore.cs b/ChatTwo/MessageStore.cs index 6fb5c6e..a3d911b 100644 --- a/ChatTwo/MessageStore.cs +++ b/ChatTwo/MessageStore.cs @@ -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