From dfd8eb178fd06057bb02cd8cc014bc3e2e1564dd Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 8 Jun 2022 10:52:31 -0300 Subject: [PATCH] [db] improve loading of versions faster permission loading and more tests --- .../dbTest/java/org/fdroid/database/DbTest.kt | 2 + .../java/org/fdroid/database/TestUtils.kt | 4 + .../java/org/fdroid/database/VersionTest.kt | 194 ++++++++++++++---- .../org/fdroid/database/DbUpdateChecker.kt | 4 +- .../main/java/org/fdroid/database/Version.kt | 20 +- .../java/org/fdroid/database/VersionDao.kt | 110 +++++----- 6 files changed, 226 insertions(+), 108 deletions(-) diff --git a/database/src/dbTest/java/org/fdroid/database/DbTest.kt b/database/src/dbTest/java/org/fdroid/database/DbTest.kt index 36295b058..33e3c4344 100644 --- a/database/src/dbTest/java/org/fdroid/database/DbTest.kt +++ b/database/src/dbTest/java/org/fdroid/database/DbTest.kt @@ -30,6 +30,7 @@ internal abstract class DbTest { internal lateinit var repoDao: RepositoryDaoInt internal lateinit var appDao: AppDaoInt + internal lateinit var appPrefsDao: AppPrefsDaoInt internal lateinit var versionDao: VersionDaoInt internal lateinit var db: FDroidDatabaseInt private val testCoroutineDispatcher = Dispatchers.Unconfined @@ -45,6 +46,7 @@ internal abstract class DbTest { .build() repoDao = db.getRepositoryDao() appDao = db.getAppDao() + appPrefsDao = db.getAppPrefsDao() versionDao = db.getVersionDao() mockkObject(FDroidDatabaseHolder) diff --git a/database/src/dbTest/java/org/fdroid/database/TestUtils.kt b/database/src/dbTest/java/org/fdroid/database/TestUtils.kt index 6c03fd856..2ce212fac 100644 --- a/database/src/dbTest/java/org/fdroid/database/TestUtils.kt +++ b/database/src/dbTest/java/org/fdroid/database/TestUtils.kt @@ -11,6 +11,7 @@ import org.junit.Assert import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.test.assertEquals +import kotlin.test.fail internal object TestUtils { @@ -106,4 +107,7 @@ internal object TestUtils { return data[0] as T? } + fun LiveData.getOrFail(): T { + return getOrAwaitValue() ?: fail() + } } diff --git a/database/src/dbTest/java/org/fdroid/database/VersionTest.kt b/database/src/dbTest/java/org/fdroid/database/VersionTest.kt index 549e53456..5fe727c49 100644 --- a/database/src/dbTest/java/org/fdroid/database/VersionTest.kt +++ b/database/src/dbTest/java/org/fdroid/database/VersionTest.kt @@ -2,7 +2,8 @@ package org.fdroid.database import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.fdroid.database.TestUtils.getOrAwaitValue +import org.fdroid.database.TestUtils.getOrFail +import org.fdroid.index.v2.PackageVersionV2 import org.fdroid.test.TestAppUtils.getRandomMetadataV2 import org.fdroid.test.TestRepoUtils.getRandomRepo import org.fdroid.test.TestUtils.getRandomString @@ -20,24 +21,46 @@ internal class VersionTest : DbTest() { @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - private val packageId = getRandomString() - private val versionId = getRandomString() + private val packageName = getRandomString() + private val packageVersion1 = getRandomPackageVersionV2() + private val packageVersion2 = getRandomPackageVersionV2() + private val packageVersion3 = getRandomPackageVersionV2() + private val versionId1 = packageVersion1.file.sha256 + private val versionId2 = packageVersion2.file.sha256 + private val versionId3 = packageVersion3.file.sha256 + private val isCompatible1 = Random.nextBoolean() + private val isCompatible2 = Random.nextBoolean() + private val packageVersions = mapOf( + versionId1 to packageVersion1, + versionId2 to packageVersion2, + ) + + private fun getVersion1(repoId: Long) = + packageVersion1.toVersion(repoId, packageName, versionId1, isCompatible1) + + private fun getVersion2(repoId: Long) = + packageVersion2.toVersion(repoId, packageName, versionId2, isCompatible2) + + private val compatChecker: (PackageVersionV2) -> Boolean = { + when (it.file.sha256) { + versionId1 -> isCompatible1 + versionId2 -> isCompatible2 + else -> fail() + } + } @Test fun insertGetDeleteSingleVersion() { val repoId = repoDao.insertOrReplace(getRandomRepo()) - appDao.insert(repoId, packageId, getRandomMetadataV2()) - val packageVersion = getRandomPackageVersionV2() - val isCompatible = Random.nextBoolean() - versionDao.insert(repoId, packageId, versionId, packageVersion, isCompatible) + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, versionId1, packageVersion1, isCompatible1) - val appVersions = versionDao.getAppVersions(repoId, packageId) + val appVersions = versionDao.getAppVersions(repoId, packageName) assertEquals(1, appVersions.size) val appVersion = appVersions[0] - assertEquals(versionId, appVersion.version.versionId) - val version = packageVersion.toVersion(repoId, packageId, versionId, isCompatible) - assertEquals(version, appVersion.version) - val manifest = packageVersion.manifest + assertEquals(versionId1, appVersion.version.versionId) + assertEquals(getVersion1(repoId), appVersion.version) + val manifest = packageVersion1.manifest assertEquals(manifest.usesPermission.toSet(), appVersion.usesPermission?.toSet()) assertEquals(manifest.usesPermissionSdk23.toSet(), appVersion.usesPermissionSdk23?.toSet()) assertEquals( @@ -45,42 +68,35 @@ internal class VersionTest : DbTest() { appVersion.version.manifest.features?.toSet() ) - val versionedStrings = versionDao.getVersionedStrings(repoId, packageId) + val versionedStrings = versionDao.getVersionedStrings(repoId, packageName) val expectedSize = manifest.usesPermission.size + manifest.usesPermissionSdk23.size assertEquals(expectedSize, versionedStrings.size) - versionDao.deleteAppVersion(repoId, packageId, versionId) - assertEquals(0, versionDao.getAppVersions(repoId, packageId).size) - assertEquals(0, versionDao.getVersionedStrings(repoId, packageId).size) + versionDao.deleteAppVersion(repoId, packageName, versionId1) + assertEquals(0, versionDao.getAppVersions(repoId, packageName).size) + assertEquals(0, versionDao.getVersionedStrings(repoId, packageName).size) } @Test fun insertGetDeleteTwoVersions() { // insert two versions along with required objects val repoId = repoDao.insertOrReplace(getRandomRepo()) - appDao.insert(repoId, packageId, getRandomMetadataV2()) - val packageVersion1 = getRandomPackageVersionV2() - val packageVersion2 = getRandomPackageVersionV2() - val version1 = getRandomString() - val version2 = getRandomString() - val isCompatible1 = Random.nextBoolean() - val isCompatible2 = Random.nextBoolean() - versionDao.insert(repoId, packageId, version1, packageVersion1, isCompatible1) - versionDao.insert(repoId, packageId, version2, packageVersion2, isCompatible2) + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, versionId1, packageVersion1, isCompatible1) + versionDao.insert(repoId, packageName, versionId2, packageVersion2, isCompatible2) // get app versions from DB and assign them correctly - val appVersions = versionDao.getAppVersions(packageId).getOrAwaitValue() ?: fail() + val appVersions = versionDao.getAppVersions(packageName).getOrFail() assertEquals(2, appVersions.size) - val appVersion = if (version1 == appVersions[0].version.versionId) { + val appVersion = if (versionId1 == appVersions[0].version.versionId) { appVersions[0] } else appVersions[1] - val appVersion2 = if (version2 == appVersions[0].version.versionId) { + val appVersion2 = if (versionId2 == appVersions[0].version.versionId) { appVersions[0] } else appVersions[1] // check first version matches - val exVersion1 = packageVersion1.toVersion(repoId, packageId, version1, isCompatible1) - assertEquals(exVersion1, appVersion.version) + assertEquals(getVersion1(repoId), appVersion.version) val manifest = packageVersion1.manifest assertEquals(manifest.usesPermission.toSet(), appVersion.usesPermission?.toSet()) assertEquals(manifest.usesPermissionSdk23.toSet(), appVersion.usesPermissionSdk23?.toSet()) @@ -90,8 +106,7 @@ internal class VersionTest : DbTest() { ) // check second version matches - val exVersion2 = packageVersion2.toVersion(repoId, packageId, version2, isCompatible2) - assertEquals(exVersion2, appVersion2.version) + assertEquals(getVersion2(repoId), appVersion2.version) val manifest2 = packageVersion2.manifest assertEquals(manifest2.usesPermission.toSet(), appVersion2.usesPermission?.toSet()) assertEquals(manifest2.usesPermissionSdk23.toSet(), @@ -102,9 +117,118 @@ internal class VersionTest : DbTest() { ) // delete app and check that all associated data also gets deleted - appDao.deleteAppMetadata(repoId, packageId) - assertEquals(0, versionDao.getAppVersions(repoId, packageId).size) - assertEquals(0, versionDao.getVersionedStrings(repoId, packageId).size) + appDao.deleteAppMetadata(repoId, packageName) + assertEquals(0, versionDao.getAppVersions(repoId, packageName).size) + assertEquals(0, versionDao.getVersionedStrings(repoId, packageName).size) + } + + @Test + fun versionsOnlyFromEnabledRepo() { + // insert two versions into the same repo + val repoId = repoDao.insertOrReplace(getRandomRepo()) + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, packageVersions, compatChecker) + assertEquals(2, versionDao.getAppVersions(packageName).getOrFail().size) + assertEquals(2, versionDao.getVersions(listOf(packageName)).size) + + // add another version into another repo + val repoId2 = repoDao.insertOrReplace(getRandomRepo()) + appDao.insert(repoId2, packageName, getRandomMetadataV2()) + versionDao.insert(repoId2, packageName, versionId3, packageVersion3, true) + assertEquals(3, versionDao.getAppVersions(packageName).getOrFail().size) + assertEquals(3, versionDao.getVersions(listOf(packageName)).size) + + // disable second repo + repoDao.setRepositoryEnabled(repoId2, false) + + // now only two versions get returned + assertEquals(2, versionDao.getAppVersions(packageName).getOrFail().size) + assertEquals(2, versionDao.getVersions(listOf(packageName)).size) + } + + @Test + fun versionsSortedByVersionCode() { + // insert three versions into the same repo + val repoId = repoDao.insertOrReplace(getRandomRepo()) + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, packageVersions, compatChecker) + versionDao.insert(repoId, packageName, versionId3, packageVersion3, true) + val versions1 = versionDao.getAppVersions(packageName).getOrFail() + val versions2 = versionDao.getVersions(listOf(packageName)) + assertEquals(3, versions1.size) + assertEquals(3, versions2.size) + + // check that they are sorted as expected + listOf( + packageVersion1.manifest.versionCode, + packageVersion2.manifest.versionCode, + packageVersion3.manifest.versionCode, + ).sortedDescending().forEachIndexed { i, versionCode -> + assertEquals(versionCode, versions1[i].version.manifest.versionCode) + assertEquals(versionCode, versions2[i].versionCode) + } + } + + @Test + fun getVersionsRespectsAppPrefsIgnore() { + // insert one version into the repo + val repoId = repoDao.insertOrReplace(getRandomRepo()) + val versionCode = Random.nextLong(1, Long.MAX_VALUE) + val packageVersion = getRandomPackageVersionV2(versionCode) + val versionId = packageVersion.file.sha256 + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, versionId, packageVersion, true) + assertEquals(1, versionDao.getVersions(listOf(packageName)).size) + + // default app prefs don't change result + var appPrefs = AppPrefs(packageName) + appPrefsDao.update(appPrefs) + assertEquals(1, versionDao.getVersions(listOf(packageName)).size) + + // ignore lower version code doesn't change result + appPrefs = appPrefs.toggleIgnoreVersionCodeUpdate(versionCode - 1) + appPrefsDao.update(appPrefs) + assertEquals(1, versionDao.getVersions(listOf(packageName)).size) + + // ignoring exact version code does change result + appPrefs = appPrefs.toggleIgnoreVersionCodeUpdate(versionCode) + appPrefsDao.update(appPrefs) + assertEquals(0, versionDao.getVersions(listOf(packageName)).size) + + // ignoring higher version code does change result + appPrefs = appPrefs.toggleIgnoreVersionCodeUpdate(versionCode + 1) + appPrefsDao.update(appPrefs) + assertEquals(0, versionDao.getVersions(listOf(packageName)).size) + + // ignoring all updates does change result + appPrefs = appPrefs.toggleIgnoreAllUpdates() + appPrefsDao.update(appPrefs) + assertEquals(0, versionDao.getVersions(listOf(packageName)).size) + + // not ignoring all updates brings back version + appPrefs = appPrefs.toggleIgnoreAllUpdates() + appPrefsDao.update(appPrefs) + assertEquals(1, versionDao.getVersions(listOf(packageName)).size) + } + + @Test + fun getVersionsConsidersOnlyGivenPackages() { + // insert two versions + val repoId = repoDao.insertOrReplace(getRandomRepo()) + appDao.insert(repoId, packageName, getRandomMetadataV2()) + versionDao.insert(repoId, packageName, packageVersions, compatChecker) + assertEquals(2, versionDao.getVersions(listOf(packageName)).size) + + // insert versions for a different package + val packageName2 = getRandomString() + appDao.insert(repoId, packageName2, getRandomMetadataV2()) + versionDao.insert(repoId, packageName2, packageVersions, compatChecker) + + // still only returns above versions + assertEquals(2, versionDao.getVersions(listOf(packageName)).size) + + // all versions are returned only if all packages are asked for + assertEquals(4, versionDao.getVersions(listOf(packageName, packageName2)).size) } } diff --git a/database/src/main/java/org/fdroid/database/DbUpdateChecker.kt b/database/src/main/java/org/fdroid/database/DbUpdateChecker.kt index cdf2cae30..f9ff28197 100644 --- a/database/src/main/java/org/fdroid/database/DbUpdateChecker.kt +++ b/database/src/main/java/org/fdroid/database/DbUpdateChecker.kt @@ -73,7 +73,7 @@ public class DbUpdateChecker( releaseChannels) ?: return null val versionedStrings = versionDao.getVersionedStrings( repoId = version.repoId, - packageId = version.packageId, + packageName = version.packageId, versionId = version.versionId, ) return version.toAppVersion(versionedStrings) @@ -109,7 +109,7 @@ public class DbUpdateChecker( private fun getUpdatableApp(version: Version, installedVersionCode: Long): UpdatableApp? { val versionedStrings = versionDao.getVersionedStrings( repoId = version.repoId, - packageId = version.packageId, + packageName = version.packageId, versionId = version.versionId, ) val appOverviewItem = diff --git a/database/src/main/java/org/fdroid/database/Version.kt b/database/src/main/java/org/fdroid/database/Version.kt index 7aaa85268..9b40bc545 100644 --- a/database/src/main/java/org/fdroid/database/Version.kt +++ b/database/src/main/java/org/fdroid/database/Version.kt @@ -4,6 +4,7 @@ import androidx.core.os.LocaleListCompat import androidx.room.Embedded import androidx.room.Entity import androidx.room.ForeignKey +import androidx.room.Relation import org.fdroid.database.VersionedStringType.PERMISSION import org.fdroid.database.VersionedStringType.PERMISSION_SDK_23 import org.fdroid.index.v2.ANTI_FEATURE_KNOWN_VULNERABILITY @@ -48,8 +49,7 @@ public data class Version( internal fun toAppVersion(versionedStrings: List): AppVersion = AppVersion( version = this, - usesPermission = versionedStrings.getPermissions(this), - usesPermissionSdk23 = versionedStrings.getPermissionsSdk23(this), + versionedStrings = versionedStrings, ) } @@ -72,10 +72,13 @@ internal fun PackageVersionV2.toVersion( isCompatible = isCompatible, ) -public data class AppVersion( - internal val version: Version, - val usesPermission: List? = null, - val usesPermissionSdk23: List? = null, +public data class AppVersion internal constructor( + @Embedded internal val version: Version, + @Relation( + parentColumn = "versionId", + entityColumn = "versionId", + ) + internal val versionedStrings: List?, ) { public val repoId: Long get() = version.repoId public val packageId: String get() = version.packageId @@ -84,9 +87,12 @@ public data class AppVersion( public val manifest: AppManifest get() = version.manifest public val file: FileV1 get() = version.file public val src: FileV2? get() = version.src + public val usesPermission: List? get() = versionedStrings?.getPermissions(version) + public val usesPermissionSdk23: List? + get() = versionedStrings?.getPermissionsSdk23(version) public val featureNames: List get() = version.manifest.features ?: emptyList() public val nativeCode: List get() = version.manifest.nativecode ?: emptyList() - public val releaseChannels: List = version.releaseChannels ?: emptyList() + public val releaseChannels: List get() = version.releaseChannels ?: emptyList() val antiFeatureNames: List get() { return version.antiFeatures?.map { it.key } ?: emptyList() diff --git a/database/src/main/java/org/fdroid/database/VersionDao.kt b/database/src/main/java/org/fdroid/database/VersionDao.kt index a26c724af..80d5162b0 100644 --- a/database/src/main/java/org/fdroid/database/VersionDao.kt +++ b/database/src/main/java/org/fdroid/database/VersionDao.kt @@ -1,9 +1,6 @@ package org.fdroid.database import androidx.lifecycle.LiveData -import androidx.lifecycle.distinctUntilChanged -import androidx.lifecycle.liveData -import androidx.lifecycle.map import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy.REPLACE @@ -15,7 +12,6 @@ import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.decodeFromJsonElement -import org.fdroid.database.FDroidDatabaseHolder.dispatcher import org.fdroid.database.VersionedStringType.PERMISSION import org.fdroid.database.VersionedStringType.PERMISSION_SDK_23 import org.fdroid.index.IndexParser.json @@ -25,15 +21,20 @@ import org.fdroid.index.v2.PermissionV2 import org.fdroid.index.v2.ReflectionDiffer public interface VersionDao { + /** + * Inserts new versions for a given [packageName] from a full index. + */ public fun insert( repoId: Long, - packageId: String, + packageName: String, packageVersions: Map, checkIfCompatible: (PackageVersionV2) -> Boolean, ) - public fun getAppVersions(packageId: String): LiveData> - public fun getAppVersions(repoId: Long, packageId: String): List + /** + * Returns a list of versions for the given [packageName] sorting by highest version code first. + */ + public fun getAppVersions(packageName: String): LiveData> } /** @@ -51,26 +52,26 @@ internal interface VersionDaoInt : VersionDao { @Transaction override fun insert( repoId: Long, - packageId: String, + packageName: String, packageVersions: Map, checkIfCompatible: (PackageVersionV2) -> Boolean, ) { // TODO maybe the number of queries here can be reduced packageVersions.entries.iterator().forEach { (versionId, packageVersion) -> val isCompatible = checkIfCompatible(packageVersion) - insert(repoId, packageId, versionId, packageVersion, isCompatible) + insert(repoId, packageName, versionId, packageVersion, isCompatible) } } @Transaction fun insert( repoId: Long, - packageId: String, + packageName: String, versionId: String, packageVersion: PackageVersionV2, isCompatible: Boolean, ) { - val version = packageVersion.toVersion(repoId, packageId, versionId, isCompatible) + val version = packageVersion.toVersion(repoId, packageName, versionId, isCompatible) insert(version) insert(packageVersion.manifest.getVersionedStrings(version)) } @@ -86,22 +87,22 @@ internal interface VersionDaoInt : VersionDao { fun update( repoId: Long, - packageId: String, + packageName: String, versionsDiffMap: Map?, checkIfCompatible: (PackageManifest) -> Boolean, ) { if (versionsDiffMap == null) { // no more versions, delete all - deleteAppVersion(repoId, packageId) + deleteAppVersion(repoId, packageName) } else versionsDiffMap.forEach { (versionId, jsonObject) -> if (jsonObject == null) { // delete individual version - deleteAppVersion(repoId, packageId, versionId) + deleteAppVersion(repoId, packageName, versionId) } else { - val version = getVersion(repoId, packageId, versionId) + val version = getVersion(repoId, packageName, versionId) if (version == null) { // new version, parse normally val packageVersionV2: PackageVersionV2 = json.decodeFromJsonElement(jsonObject) val isCompatible = checkIfCompatible(packageVersionV2.packageManifest) - insert(repoId, packageId, versionId, packageVersionV2, isCompatible) + insert(repoId, packageName, versionId, packageVersionV2, isCompatible) } else { // diff against existing version diffVersion(version, jsonObject, checkIfCompatible) } @@ -153,38 +154,25 @@ internal interface VersionDaoInt : VersionDao { insertNewList = { versionedStrings -> insert(versionedStrings) }, ) - override fun getAppVersions( - packageId: String, - ): LiveData> = liveData(dispatcher) { - // TODO we should probably react to changes of versioned strings as well - val versionedStrings = getVersionedStrings(packageId) - val liveData = getVersions(packageId).distinctUntilChanged().map { versions -> - versions.map { version -> version.toAppVersion(versionedStrings) } - } - emitSource(liveData) - } - @Transaction - override fun getAppVersions(repoId: Long, packageId: String): List { - val versionedStrings = getVersionedStrings(repoId, packageId) - return getVersions(repoId, packageId).map { version -> - version.toAppVersion(versionedStrings) - } - } - - @Query("""SELECT * FROM Version - WHERE repoId = :repoId AND packageId = :packageId AND versionId = :versionId""") - fun getVersion(repoId: Long, packageId: String, versionId: String): Version? - @RewriteQueriesToDropUnusedColumns @Query("""SELECT * FROM Version JOIN RepositoryPreferences AS pref USING (repoId) - WHERE pref.enabled = 1 AND packageId = :packageId - ORDER BY manifest_versionCode DESC""") - fun getVersions(packageId: String): LiveData> + WHERE pref.enabled = 1 AND packageId = :packageName + ORDER BY manifest_versionCode DESC, pref.weight DESC""") + override fun getAppVersions(packageName: String): LiveData> - @Query("SELECT * FROM Version WHERE repoId = :repoId AND packageId = :packageId") - fun getVersions(repoId: Long, packageId: String): List + /** + * Only use for testing, not sorted, does take disabled repos into account. + */ + @Transaction + @Query("""SELECT * FROM Version + WHERE repoId = :repoId AND packageId = :packageName""") + fun getAppVersions(repoId: Long, packageName: String): List + + @Query("""SELECT * FROM Version + WHERE repoId = :repoId AND packageId = :packageName AND versionId = :versionId""") + fun getVersion(repoId: Long, packageName: String, versionId: String): Version? /** * Used for finding versions that are an update, @@ -192,47 +180,41 @@ internal interface VersionDaoInt : VersionDao { */ @RewriteQueriesToDropUnusedColumns @Query("""SELECT * FROM Version - JOIN RepositoryPreferences USING (repoId) + JOIN RepositoryPreferences AS pref USING (repoId) LEFT JOIN AppPrefs USING (packageId) - WHERE RepositoryPreferences.enabled = 1 AND + WHERE pref.enabled = 1 AND manifest_versionCode > COALESCE(AppPrefs.ignoreVersionCodeUpdate, 0) AND packageId IN (:packageNames) - ORDER BY manifest_versionCode DESC, RepositoryPreferences.weight DESC""") + ORDER BY manifest_versionCode DESC, pref.weight DESC""") fun getVersions(packageNames: List): List - @RewriteQueriesToDropUnusedColumns - @Query("""SELECT * FROM VersionedString - JOIN RepositoryPreferences AS pref USING (repoId) - WHERE pref.enabled = 1 AND packageId = :packageId""") - fun getVersionedStrings(packageId: String): List - - @Query("SELECT * FROM VersionedString WHERE repoId = :repoId AND packageId = :packageId") - fun getVersionedStrings(repoId: Long, packageId: String): List + @Query("SELECT * FROM VersionedString WHERE repoId = :repoId AND packageId = :packageName") + fun getVersionedStrings(repoId: Long, packageName: String): List @Query("""SELECT * FROM VersionedString - WHERE repoId = :repoId AND packageId = :packageId AND versionId = :versionId""") + WHERE repoId = :repoId AND packageId = :packageName AND versionId = :versionId""") fun getVersionedStrings( repoId: Long, - packageId: String, + packageName: String, versionId: String, ): List - @Query("""DELETE FROM Version WHERE repoId = :repoId AND packageId = :packageId""") - fun deleteAppVersion(repoId: Long, packageId: String) + @Query("""DELETE FROM Version WHERE repoId = :repoId AND packageId = :packageName""") + fun deleteAppVersion(repoId: Long, packageName: String) @Query("""DELETE FROM Version - WHERE repoId = :repoId AND packageId = :packageId AND versionId = :versionId""") - fun deleteAppVersion(repoId: Long, packageId: String, versionId: String) + WHERE repoId = :repoId AND packageId = :packageName AND versionId = :versionId""") + fun deleteAppVersion(repoId: Long, packageName: String, versionId: String) @Query("""DELETE FROM VersionedString - WHERE repoId = :repoId AND packageId = :packageId AND versionId = :versionId""") - fun deleteVersionedStrings(repoId: Long, packageId: String, versionId: String) + WHERE repoId = :repoId AND packageId = :packageName AND versionId = :versionId""") + fun deleteVersionedStrings(repoId: Long, packageName: String, versionId: String) @Query("""DELETE FROM VersionedString WHERE repoId = :repoId - AND packageId = :packageId AND versionId = :versionId AND type = :type""") + AND packageId = :packageName AND versionId = :versionId AND type = :type""") fun deleteVersionedStrings( repoId: Long, - packageId: String, + packageName: String, versionId: String, type: VersionedStringType, )