Add new FeedDao upsert method

This commit is contained in:
Shinokuni 2024-05-04 19:29:20 +02:00
parent 052c83cb35
commit 8071f0b477
2 changed files with 154 additions and 0 deletions

View File

@ -0,0 +1,107 @@
package com.readrops.db.dao
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.account.Account
import com.readrops.db.entities.account.AccountType
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class NewFeedDaoTest {
private lateinit var database: Database
private lateinit var account: Account
@Before
fun before() = runTest {
val context = ApplicationProvider.getApplicationContext<Context>()
database = Room.inMemoryDatabaseBuilder(context, Database::class.java).build()
account = Account(accountType = AccountType.LOCAL).apply {
id = database.newAccountDao().insert(this).toInt()
}
repeat(2) { time ->
database.newFolderDao().insert(
Folder(
name = "Folder $time",
remoteId = "folder_$time",
accountId = account.id
)
)
}
repeat(3) { time ->
database.newFeedDao().insert(
Feed(
name = "Feed $time",
remoteId = "feed_$time",
remoteFolderId = "folder_${if (time % 2 == 0) 0 else 1}",
accountId = account.id
)
)
}
}
@After
fun after() {
database.close()
}
@Test
fun upsertFeedsTest() = runTest {
val newFeeds = listOf(
// updated feed (name + folder to null)
Feed(
name = "New Feed 0",
remoteId = "feed_0",
remoteFolderId = null,
accountId = account.id
),
// deleted feed
/*Feed(
name = "Feed 1",
remoteId = "feed_1",
folderId = 1,
accountId = account.id
),*/
// updated feed (folder change)
Feed(
name = "Feed 2",
remoteId = "feed_2",
remoteFolderId = "folder_1",
accountId = account.id
),
// inserted feed
Feed(
name = "Feed 3",
remoteId = "feed_3",
folderId = 1,
accountId = account.id
),
)
database.newFeedDao().upsertFeeds(newFeeds, account)
val allFeeds = database.newFeedDao().selectFeeds(account.id)
assertTrue(allFeeds.any { it.name == "New Feed 0" && it.folderId == null })
assertTrue(allFeeds.any { it.remoteId == "feed_2" && it.folderId == 2 })
assertFalse(allFeeds.any { it.remoteId == "feed_1" })
assertTrue(allFeeds.any { it.remoteId == "feed_3" })
}
}

View File

@ -3,9 +3,11 @@ package com.readrops.db.dao.newdao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Item
import com.readrops.db.entities.account.Account
import com.readrops.db.pojo.FeedWithCount
import kotlinx.coroutines.flow.Flow
@ -35,4 +37,49 @@ abstract class NewFeedDao : NewBaseDao<Feed> {
@Query("Select count(*) from Feed Where account_id = :accountId")
abstract suspend fun selectFeedCount(accountId: Int): Int
@Query("Select remoteId From Feed Where account_id = :accountId")
abstract suspend fun selectFeedRemoteIds(accountId: Int): MutableList<String>
@Query("Select id From Folder Where remoteId = :remoteId And account_id = :accountId")
abstract suspend fun selectRemoteFolderLocalId(remoteId: String, accountId: Int): Int
@Query("Update Feed set name = :name, folder_id = :folderId Where remoteId = :remoteFeedId And account_id = :accountId")
abstract fun updateFeedNameAndFolder(remoteFeedId: String, accountId: Int, name: String, folderId: Int?)
@Query("Delete from Feed Where remoteId in (:ids) And account_id = :accountId")
abstract fun deleteByIds(ids: List<String>, accountId: Int)
/**
* Insert, update and delete feeds by account
*
* @param feeds feeds to insert or update
* @param account owner of the feeds
* @return the list of the inserted feeds ids
*/
@Transaction
suspend fun upsertFeeds(feeds: List<Feed>, account: Account): List<Long> {
val localFeedIds = selectFeedRemoteIds(account.id)
val feedsToInsert = feeds.filter { feed -> localFeedIds.none { localFeedId -> feed.remoteId == localFeedId } }
val feedsToDelete = localFeedIds.filter { localFeedId -> feeds.none { feed -> localFeedId == feed.remoteId } }
// feeds to update
feeds.filter { feed -> localFeedIds.any { localFeedId -> feed.remoteId == localFeedId } }
.forEach { feed ->
val folderId: Int? = if (feed.remoteFolderId == null) {
null
} else {
selectRemoteFolderLocalId(feed.remoteFolderId!!, account.id)
}
updateFeedNameAndFolder(feed.remoteId!!, account.id, feed.name!!, folderId)
}
if (feedsToDelete.isNotEmpty()) {
deleteByIds(feedsToDelete, account.id)
}
return insert(feedsToInsert)
}
}