diff --git a/core/database/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt b/core/database/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt index e876458ee..200aa9f1d 100644 --- a/core/database/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt +++ b/core/database/src/commonMain/kotlin/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt @@ -16,61 +16,123 @@ package com.google.samples.apps.nowinandroid.core.database.dao -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query -import androidx.room.Upsert +import app.cash.sqldelight.coroutines.asFlow +import app.cash.sqldelight.coroutines.mapToList +import app.cash.sqldelight.coroutines.mapToOne +import com.google.samples.apps.nowinandroid.core.database.NiaDatabase import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map /** * DAO for [TopicEntity] access */ -@Dao -interface TopicDao { - @Query( - value = """ - SELECT * FROM topics - WHERE id = :topicId - """, - ) - fun getTopicEntity(topicId: String): Flow - @Query(value = "SELECT * FROM topics") - fun getTopicEntities(): Flow> +class TopicDao(db: NiaDatabase, private val dispatcher: CoroutineDispatcher) { - @Query(value = "SELECT * FROM topics") - suspend fun getOneOffTopicEntities(): List + private val query = db.topicsQueries - @Query( - value = """ - SELECT * FROM topics - WHERE id IN (:ids) - """, - ) - fun getTopicEntities(ids: Set): Flow> + fun getTopicEntity(topicId: String): Flow { + return query.getTopicEntity(topicId) { id, name, shortDescription, longDescription, url, imageUrl -> + TopicEntity( + id = id, + name = name, + shortDescription = shortDescription, + longDescription = longDescription, + url = url, + imageUrl = imageUrl, + ) + } + .asFlow() + .mapToOne(dispatcher) + } + + fun getTopicEntities(): Flow> { + return query.getOneOffTopicEntities { id, name, shortDescription, longDescription, url, imageUrl -> + TopicEntity( + id = id, + name = name, + shortDescription = shortDescription, + longDescription = longDescription, + url = url, + imageUrl = imageUrl, + ) + } + .asFlow() + .mapToList(dispatcher) + } + + suspend fun getOneOffTopicEntities(): List { + // TODO: Use flow? + return query.getOneOffTopicEntities { id, name, shortDescription, longDescription, url, imageUrl -> + TopicEntity( + id = id, + name = name, + shortDescription = shortDescription, + longDescription = longDescription, + url = url, + imageUrl = imageUrl, + ) + }.executeAsList() + } + + fun getTopicEntities(ids: Set): Flow> { + return query.getTopicEntities { id, name, shortDescription, longDescription, url, imageUrl -> + TopicEntity( + id = id, + name = name, + shortDescription = shortDescription, + longDescription = longDescription, + url = url, + imageUrl = imageUrl, + ) + } + .asFlow() + .mapToList(dispatcher) + .map { + it.filter { topic -> topic.id in ids } + } + } /** * Inserts [topicEntities] into the db if they don't exist, and ignores those that do */ - @Insert(onConflict = OnConflictStrategy.IGNORE) - suspend fun insertOrIgnoreTopics(topicEntities: List): List + suspend fun insertOrIgnoreTopics(topicEntities: List): List { + topicEntities.map { + query.insertOrIgnoreTopic( + id = it.id, + name = it.name, + short_description = it.shortDescription, + long_description = it.longDescription, + url = it.url, + image_url = it.imageUrl, + ) + } + // TODO return the ids of the inserted topics + return topicEntities.mapNotNull { it.id.toLongOrNull() } + } /** * Inserts or updates [entities] in the db under the specified primary keys */ - @Upsert - suspend fun upsertTopics(entities: List) + suspend fun upsertTopics(entities: List) { + entities.forEach { + query.upsertTopic( + id = it.id, + name = it.name, + short_description = it.shortDescription, + long_description = it.longDescription, + url = it.url, + image_url = it.imageUrl, + ) + } + } /** * Deletes rows in the db matching the specified [ids] */ - @Query( - value = """ - DELETE FROM topics - WHERE id in (:ids) - """, - ) - suspend fun deleteTopics(ids: List) + suspend fun deleteTopics(ids: List) { + query.deleteTopics(ids) + } } diff --git a/core/database/src/commonMain/sqldelight/com/google/samples/apps/nowinandroid/core/database/Topics.sq b/core/database/src/commonMain/sqldelight/com/google/samples/apps/nowinandroid/core/database/Topics.sq index 7aa803a34..90359bb5a 100644 --- a/core/database/src/commonMain/sqldelight/com/google/samples/apps/nowinandroid/core/database/Topics.sq +++ b/core/database/src/commonMain/sqldelight/com/google/samples/apps/nowinandroid/core/database/Topics.sq @@ -16,11 +16,11 @@ SELECT * FROM topic; getOneOffTopicEntities: SELECT * FROM topic; -insertOrIgnoreTopics: +insertOrIgnoreTopic: INSERT OR IGNORE INTO topic(id, name, short_description, long_description, url, image_url) VALUES (?, ?, ?, ?, ?, ?); -upsertTopics: +upsertTopic: INSERT INTO topic(id, name, short_description, long_description, url, image_url) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET @@ -31,4 +31,4 @@ url = excluded.url, image_url = excluded.image_url; deleteTopics: -DELETE FROM topic WHERE id IN (:ids); +DELETE FROM topic WHERE id IN :ids;