Skip to content

Commit

Permalink
Fix crash during database migration_5_6 on Android 10 and below
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksey-saenko committed Mar 26, 2024
1 parent 970a92e commit 0b23eee
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.mrsep.musicrecognizer.data.database.migration

import androidx.core.database.getStringOrNull
import androidx.sqlite.db.SupportSQLiteDatabase

internal object DatabaseMigrationUtils {

internal fun SupportSQLiteDatabase.isSQLiteVersionAtLeast(version: String): Boolean? {
val thisVersion = querySQLiteVersion() ?: return null
return runCatching { (compareSQLiteVersions(thisVersion, version) != -1) }.getOrNull()
}

private fun SupportSQLiteDatabase.querySQLiteVersion(): String? {
return query("SELECT sqlite_version()").use {
if (!it.moveToNext()) return null
it.getStringOrNull(0)
}
}

private fun compareSQLiteVersions(version1: String, version2: String): Int {
val pattern = Regex("^\\d+(\\.\\d+)*\$")
if (!pattern.matches(version1)) {
throw IllegalArgumentException("Incorrect version format:$version1")
}
if (!pattern.matches(version2)) {
throw IllegalArgumentException("Incorrect version format:$version2")
}
val partsThis = version1.split('.')
val partsOther = version2.split('.')
val maxLength = maxOf(partsThis.size, partsOther.size)
for (i in 0 until maxLength) {
val partThis = partsThis.getOrNull(i)?.toIntOrNull() ?: 0
val partOther = partsOther.getOrNull(i)?.toIntOrNull() ?: 0

when {
partThis > partOther -> return 1
partThis < partOther -> return -1
}
}
return 0
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.mrsep.musicrecognizer.data.database.migration

import android.os.Build
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.mrsep.musicrecognizer.data.database.migration.DatabaseMigrationUtils.isSQLiteVersionAtLeast

internal val Migration5To6 = object : Migration(5, 6) {

Expand All @@ -11,9 +13,19 @@ internal val Migration5To6 = object : Migration(5, 6) {
}

private fun migrateTrackTable(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE track RENAME COLUMN last_recognition_date TO recognition_date")
db.execSQL("ALTER TABLE track ADD COLUMN recognized_by TEXT NOT NULL DEFAULT 'Audd'")
db.execSQL("ALTER TABLE track ADD COLUMN is_viewed INTEGER NOT NULL DEFAULT 1")
// APIs lower than 30 have SQLite 3.22 by default, which does not support RENAME COLUMN
val renameAllowed = db.isSQLiteVersionAtLeast("3.25.0")
?: (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q)
if (renameAllowed) {
db.execSQL("ALTER TABLE track RENAME COLUMN last_recognition_date TO recognition_date")
db.execSQL("ALTER TABLE track ADD COLUMN recognized_by TEXT NOT NULL DEFAULT 'Audd'")
db.execSQL("ALTER TABLE track ADD COLUMN is_viewed INTEGER NOT NULL DEFAULT 1")
} else {
db.execSQL("CREATE TABLE track_new (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `artist` TEXT NOT NULL, `album` TEXT, `release_date` INTEGER, `duration` INTEGER, `recognized_at` INTEGER, `recognized_by` TEXT NOT NULL, `recognition_date` INTEGER NOT NULL, `lyrics` TEXT, `link_artwork` TEXT, `link_amazon_music` TEXT, `link_anghami` TEXT, `link_apple_music` TEXT, `link_audiomack` TEXT, `link_audius` TEXT, `link_boomplay` TEXT, `link_deezer` TEXT, `link_musicbrainz` TEXT, `link_napster` TEXT, `link_pandora` TEXT, `link_soundcloud` TEXT, `link_spotify` TEXT, `link_tidal` TEXT, `link_yandex_music` TEXT, `link_youtube` TEXT, `link_youtube_music` TEXT, `is_favorite` INTEGER NOT NULL, `is_viewed` INTEGER NOT NULL, `theme_seed_color` INTEGER, PRIMARY KEY(`id`))")
db.execSQL("INSERT INTO track_new (`id`, `title`, `artist`, `album`, `release_date`, `duration`, `recognized_at`, `recognized_by`, `recognition_date`, `lyrics`, `link_artwork`, `link_amazon_music`, `link_anghami`, `link_apple_music`, `link_audiomack`, `link_audius`, `link_boomplay`, `link_deezer`, `link_musicbrainz`, `link_napster`, `link_pandora`, `link_soundcloud`, `link_spotify`, `link_tidal`, `link_yandex_music`, `link_youtube`, `link_youtube_music`, `is_favorite`, `is_viewed`, `theme_seed_color`) SELECT `id`, `title`, `artist`, `album`, `release_date`, `duration`, `recognized_at`, 'Audd' AS `recognized_by`, `last_recognition_date` AS `recognition_date`, `lyrics`, `link_artwork`, `link_amazon_music`, `link_anghami`, `link_apple_music`, `link_audiomack`, `link_audius`, `link_boomplay`, `link_deezer`, `link_musicbrainz`, `link_napster`, `link_pandora`, `link_soundcloud`, `link_spotify`, `link_tidal`, `link_yandex_music`, `link_youtube`, `link_youtube_music`, `is_favorite`, 1 AS `is_viewed`, `theme_seed_color` FROM track")
db.execSQL("DROP TABLE track")
db.execSQL("ALTER TABLE track_new RENAME TO track")
}
db.execSQL("CREATE INDEX index_track_is_viewed ON track (is_viewed)")
}

Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/16.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Fixed crash during database migration on app startup on Android 10 and below
1 change: 1 addition & 0 deletions fastlane/metadata/android/ru/changelogs/16.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Исправлен вылет во время миграции базы данных при запуске приложения на Android 10 и ниже

0 comments on commit 0b23eee

Please sign in to comment.