exch-bms2 / beatoraja

Cross-platform rhythm game based on Java and libGDX.
GNU General Public License v3.0
623 stars 146 forks source link

楽曲DBに不正なレコードがあるとフォルダを開いた時にクラッシュすることがある #770

Open Getaji opened 7 months ago

Getaji commented 7 months ago

以前Issueが立てられて解決済としてクローズされたこちらの問題についてです: https://github.com/exch-bms2/beatoraja/issues/746

説明

上記のIssueは「持っていない譜面をFAVORITE登録すると不正なレコードが追加される」という不具合です。「不正なレコードが追加される」は修正されましたが、修正前に「持っていない譜面をFAVORITE登録する」という操作を行っていた場合、データベース (songdata.dbsong テーブル) に残留した不正なレコードによって「難易度表のフォルダを開くとフリーズする」という問題が依然として発生します。これは SongBar が行っている以下の重複除去処理が sha256 を持たない songs を想定していないためです:

https://github.com/exch-bms2/beatoraja/blob/45c9ab2307ffbe03b7d136498e04a4990f5dc5bf/src/bms/player/beatoraja/select/bar/SongBar.java#L101

修正案

安直に対応するのであれば、 SQLiteSongDatabaseAccessor::getSongDatas(String[] hashes) &類似するメソッドの検索クエリに sha256 <> ''path IS NOT NULL を追加することで、取得するデータから不正なレコードを除外できます。

https://github.com/exch-bms2/beatoraja/blob/45c9ab2307ffbe03b7d136498e04a4990f5dc5bf/src/bms/player/beatoraja/song/SQLiteSongDatabaseAccessor.java#L159

-           List<SongData> m = qr.query("SELECT * FROM song WHERE md5 IN (" + md5str.toString() + ") OR sha256 IN ("
+           List<SongData> m = qr.query("SELECT * FROM song WHERE path IS NOT NULL AND (md5 IN (" + md5str.toString() + ") OR sha256 IN ("

ですが、取得される前に不正なレコード自体をDBから削除したほうがより安全だと思われます。方法としては「SQLiteSongDatabaseAccessor の初期化時に DELETE クエリを走らせる」といったものを検討していますが、他に適切な方法があればご提案いただければ幸いです (できれば自動DBマイグレーションのように最新版で一度だけ実行すればよしとしたい) 。