refactor(core): switch from room to sqldelight

sqldelight provides far more control over the sql and allows me to make
more optimisations such as removing generated rowid etc. sql also just
looks better than the annotation hell from room.
This commit is contained in:
Cilly Leang 2026-05-02 02:31:18 +10:00
parent ff2af310fb
commit f1770744db
Signed by: cilly
GPG key ID: 6500251E087653C9
74 changed files with 601 additions and 5037 deletions

View file

@ -45,7 +45,7 @@ kotlin {
implementation(libs.kotlinx.serialization.protobuf)
implementation(projects.core)
implementation(projects.core.room)
implementation(projects.core.sqld)
}
iosMain.dependencies {
implementation(libs.ktor.client.darwin)

View file

@ -20,7 +20,7 @@ import moe.lava.banksia.core.data.sources.stop.StopLocalDataSource
import moe.lava.banksia.core.data.sources.stop.StopRemoteDataSource
import moe.lava.banksia.core.data.sources.stoptime.StopTimeLocalDataSource
import moe.lava.banksia.core.data.sources.stoptime.StopTimeRemoteDataSource
import moe.lava.banksia.core.room.roomDiModule
import moe.lava.banksia.core.sqld.sqldDiModule
import moe.lava.banksia.core.util.log
import moe.lava.banksia.data.ptv.PtvService
import org.koin.core.module.dsl.singleOf
@ -28,7 +28,7 @@ import org.koin.dsl.bind
import org.koin.dsl.module
val clientDataDiModule = module {
includes(roomDiModule)
includes(sqldDiModule)
// HTTP Clients
singleOf(::PtvService)

View file

@ -4,6 +4,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.lava.banksia.core.data.sources.route.RouteLocalDataSource
import moe.lava.banksia.core.data.sources.route.RouteRemoteDataSource
import moe.lava.banksia.core.sqld.mappers.asModel
internal class ClientRouteRepository internal constructor(
private val local: RouteLocalDataSource,

View file

@ -4,6 +4,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.lava.banksia.core.data.sources.stop.StopLocalDataSource
import moe.lava.banksia.core.data.sources.stop.StopRemoteDataSource
import moe.lava.banksia.core.sqld.mappers.asModel
internal class ClientStopRepository internal constructor(
private val local: StopLocalDataSource,

View file

@ -1,11 +1,22 @@
package moe.lava.banksia.core.data.sources.route
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import moe.lava.banksia.core.model.Route
import moe.lava.banksia.core.room.dao.RouteDao
import moe.lava.banksia.core.room.entity.asEntity
import moe.lava.banksia.core.sqld.RouteQueries
import moe.lava.banksia.core.sqld.mappers.asDb
internal class RouteLocalDataSource(private val dao: RouteDao) {
suspend fun get(id: String) = dao.get(id)
suspend fun getAll() = dao.getAll()
suspend fun save(vararg routes: Route) = dao.insertOrReplaceAll(*routes.map { it.asEntity() }.toTypedArray())
internal class RouteLocalDataSource(private val queries: RouteQueries) {
suspend fun get(id: String) = withContext(Dispatchers.IO) { queries.get(id).executeAsOneOrNull() }
suspend fun getAll() = withContext(Dispatchers.IO) { queries.getAll().executeAsList() }
suspend fun save(vararg routes: Route) {
withContext(Dispatchers.IO) {
queries.transaction {
routes.forEach {
queries.insert(it.asDb())
}
}
}
}
}

View file

@ -1,12 +1,22 @@
package moe.lava.banksia.core.data.sources.stop
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import moe.lava.banksia.core.model.Stop
import moe.lava.banksia.core.room.dao.RouteDao
import moe.lava.banksia.core.room.dao.StopDao
import moe.lava.banksia.core.room.entity.asEntity
import moe.lava.banksia.core.sqld.StopQueries
import moe.lava.banksia.core.sqld.mappers.asDb
internal class StopLocalDataSource(private val dao: StopDao, private val routeDao: RouteDao) {
suspend fun get(id: String) = dao.get(id)
suspend fun getByRoute(id: String) = routeDao.stops(id)
suspend fun save(vararg stops: Stop) = dao.insertOrReplaceAll(*stops.map { it.asEntity() }.toTypedArray())
internal class StopLocalDataSource(private val queries: StopQueries) {
suspend fun get(id: String) = withContext(Dispatchers.IO) { queries.get(id).executeAsOneOrNull() }
suspend fun getByRoute(id: String) = withContext(Dispatchers.IO) { queries.getByRoute(id).executeAsList() }
suspend fun save(vararg stops: Stop) {
withContext(Dispatchers.IO) {
queries.transaction {
stops.forEach {
queries.insert(it.asDb())
}
}
}
}
}

View file

@ -1,28 +1,35 @@
package moe.lava.banksia.core.data.sources.stoptime
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.todayIn
import moe.lava.banksia.core.model.StopTimeDated
import moe.lava.banksia.core.model.atDate
import moe.lava.banksia.core.room.dao.StopTimeDao
import moe.lava.banksia.core.sqld.StopTimeQueries
import moe.lava.banksia.core.sqld.mappers.asModel
import moe.lava.banksia.core.util.serialise
import kotlin.time.Clock
internal class StopTimeLocalDataSource(
private val stopTimeDao: StopTimeDao,
private val queries: StopTimeQueries,
) {
suspend fun getAtStop(
stopId: String,
date: LocalDate = Clock.System.todayIn(TimeZone.currentSystemDefault()),
): List<StopTimeDated> {
return stopTimeDao
.getForStopDated(
stopId,
listOf(date.dayOfWeek).serialise(),
date.toEpochDays().toInt(),
)
.map { it.asModel().atDate(date) }
.sortedBy { it.departureTime }
return withContext(Dispatchers.IO) {
queries
.getForStopDated(
listOf(date.dayOfWeek).serialise().toLong(),
date.toEpochDays(),
stopId,
)
.executeAsList()
.map { it.asModel().atDate(date) }
.sortedBy { it.departureTime }
}
}
}