As far as I can see SqlDelight Query object doesn't have any way to query items one by one instead of everything as a whole like executeAsList(). I have a large table to process and I can't load everything into memory.
The execute() function comes in close, since that allows me to run each result through a mapper, but you lose type safety and are back to raw sqlite columns and casting:
val a = mDb.testQueries.selectAll().execute { cursor ->
while (cursor.next().value) {
println("cursor $cursor")
}
QueryResult.Unit
}
Another alternative is passing the mapper as the constructor to the query, so you regain the type safety. Unfortunately this has to return the whole result, so it is wasting memory returning a list as long as the whole table.
mDb.testQueries.selectAll { id, foo, bar, timestamp ->
println("Running on id $id, timestamp $timestamp")
}.executeAsList()
Is there really no way to query a big table other than writing my own pagination code?
UPDATE: Extension function based on answer:
fun <RowType : Any> Query<RowType>.iterate(block: (RowType) -> Unit) {
execute { cursor ->
while (cursor.next().value) {
block(mapper(cursor))
}
QueryResult.Unit
}
}
…
mDb.testQueries.selectAll().iterate { id, foo, bar, timestamp ->
…
}
You can use mapper
which is part of ExecutableQuery
, same as executeAsList
does:
val query = mDb.testQueries.selectAll()
query.execute { cursor ->
while (cursor.next().value) {
val typeSafeValue = query.mapper(cursor)
// process and release
}
QueryResult.Unit
}