// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using osu.Framework.Logging; using osu.Game.Database; using osu.Game.Screens.Menu; using SQLite.Net; using SQLiteNetExtensions.Extensions; namespace osu.Game.Beatmaps { /// /// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing /// public class BeatmapDatabase : DatabaseStore { public event Action BeatmapSetAdded; public event Action BeatmapSetRemoved; public BeatmapDatabase(SQLiteConnection connection) : base(connection) { } protected override Type[] ValidTypes => new[] { typeof(BeatmapSetInfo), typeof(BeatmapInfo), typeof(BeatmapMetadata), typeof(BeatmapDifficulty), }; protected override void Prepare(bool reset = false) { Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); Connection.CreateTable(); if (reset) { Connection.DropTable(); Connection.DropTable(); Connection.DropTable(); Connection.DropTable(); } deletePending(); } public void Import(IEnumerable beatmapSets) { lock (Connection) { Connection.BeginTransaction(); foreach (var s in beatmapSets) { Connection.InsertOrReplaceWithChildren(s, true); BeatmapSetAdded?.Invoke(s); } Connection.Commit(); } } public void Delete(IEnumerable beatmapSets) { foreach (var s in beatmapSets) { s.DeletePending = true; Update(s, false); BeatmapSetRemoved?.Invoke(s); } } private void deletePending() { foreach (var b in GetAllWithChildren(b => b.DeletePending)) { if (b.Hash == Intro.MENU_MUSIC_BEATMAP_HASH) // this is a bit hacky, but will do for now. continue; try { foreach (var i in b.Beatmaps) { if (i.Metadata != null) Connection.Delete(i.Metadata); if (i.Difficulty != null) Connection.Delete(i.Difficulty); Connection.Delete(i); } if (b.Metadata != null) Connection.Delete(b.Metadata); Connection.Delete(b); } catch (Exception e) { Logger.Error(e, $@"Could not delete beatmap {b}"); } } //this is required because sqlite migrations don't work, initially inserting nulls into this field. //see https://github.com/praeclarum/sqlite-net/issues/326 Connection.Query("UPDATE BeatmapSetInfo SET DeletePending = 0 WHERE DeletePending IS NULL"); } } }