diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs index 61e87a6621..51c78ff442 100644 --- a/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCasePlaySongSelect.cs @@ -6,6 +6,7 @@ using osu.Desktop.VisualTests.Platform; using osu.Framework.Testing; using osu.Framework.MathUtils; using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.Rulesets; using osu.Game.Screens.Select; using osu.Game.Screens.Select.Filter; @@ -29,6 +30,7 @@ namespace osu.Desktop.VisualTests.Tests var storage = new TestStorage(@"TestCasePlaySongSelect"); var backingDatabase = storage.GetDatabase(@"client"); + backingDatabase.CreateTable(); rulesets = new RulesetStore(backingDatabase); manager = new BeatmapManager(storage, null, backingDatabase, rulesets); diff --git a/osu.Game/Beatmaps/BeatmapStore.cs b/osu.Game/Beatmaps/BeatmapStore.cs index 4a7336535e..f9019537a0 100644 --- a/osu.Game/Beatmaps/BeatmapStore.cs +++ b/osu.Game/Beatmaps/BeatmapStore.cs @@ -17,6 +17,12 @@ namespace osu.Game.Beatmaps public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; + /// + /// The current version of this store. Used for migrations (see ). + /// The initial version is 1. + /// + protected override int StoreVersion => 1; + public BeatmapStore(SQLiteConnection connection) : base(connection) { @@ -50,6 +56,33 @@ namespace osu.Game.Beatmaps cleanupPendingDeletions(); } + /// + /// Perform migrations between two store versions. + /// + /// The current store version. This will be zero on a fresh database initialisation. + /// The target version which we are migrating to (equal to the current ). + protected override void PerformMigration(int currentVersion, int newVersion) + { + base.PerformMigration(currentVersion, newVersion); + + while (currentVersion++ < newVersion) + { + switch (currentVersion) + { + case 1: + // initialising from a version before we had versioning (or a fresh install). + + // force adding of Protected column (not automatically migrated). + Connection.MigrateTable(); + + // remove all existing beatmaps. + foreach (var b in Connection.GetAllWithChildren(null, true)) + Connection.Delete(b, true); + break; + } + } + } + /// /// Add a to the database. /// diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index 8366775483..bb61fc1870 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -17,6 +17,8 @@ namespace osu.Game.Database protected readonly Storage Storage; protected readonly SQLiteConnection Connection; + protected virtual int StoreVersion => 1; + protected DatabaseBackedStore(SQLiteConnection connection, Storage storage = null) { Storage = storage; @@ -31,6 +33,28 @@ namespace osu.Game.Database Logger.Error(e, $@"Failed to initialise the {GetType()}! Trying again with a clean database..."); Prepare(true); } + + checkMigrations(); + } + + private void checkMigrations() + { + var storeName = GetType().Name; + + var reportedVersion = Connection.Table().FirstOrDefault(s => s.StoreName == storeName) ?? new StoreVersion + { + StoreName = storeName, + Version = 0 + }; + + if (reportedVersion.Version != StoreVersion) + PerformMigration(reportedVersion.Version, reportedVersion.Version = StoreVersion); + + Connection.InsertOrReplace(reportedVersion); + } + + protected virtual void PerformMigration(int currentVersion, int newVersion) + { } /// diff --git a/osu.Game/Database/StoreVersion.cs b/osu.Game/Database/StoreVersion.cs new file mode 100644 index 0000000000..00314875a6 --- /dev/null +++ b/osu.Game/Database/StoreVersion.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using SQLite.Net.Attributes; + +namespace osu.Game.Database +{ + public class StoreVersion + { + [PrimaryKey] + public string StoreName { get; set; } + + public int Version { get; set; } + } +} diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index b507aa2315..0dec4228de 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -18,6 +18,7 @@ using osu.Game.Graphics.Processing; using osu.Game.Online.API; using SQLite.Net; using osu.Framework.Graphics.Performance; +using osu.Game.Database; using osu.Game.IO; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; @@ -97,6 +98,8 @@ namespace osu.Game SQLiteConnection connection = Host.Storage.GetDatabase(@"client"); + connection.CreateTable(); + dependencies.Cache(RulesetStore = new RulesetStore(connection)); dependencies.Cache(FileStore = new FileStore(connection, Host.Storage)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host)); diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f8509314be..5ac76ed00e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -80,6 +80,7 @@ +