I see a common pattern in my code. I have sorted results from a database and I need to emit them in a nested structure. I would like this to stream and so I want to have as few records in memory at a time. Using TravesableLike.groupBy assumes that the data is not sorted and so it needlessly fills a mutable map. I would like to keep this truly streaming. Is scalaz-stream useful here?
val sql = """select grandparent_id, parent_id, child_id
from children
where grandparent_id = ?
order by grandparent_id, parent_id, child_id"""
def elementsR[P, R](invoker: Invoker[P, R], param: P): Process[Task, R] =
// Invoker.elements returns trait CloseableIterator[+T] extends Iterator[T] with Closeable
resource(Task.delay(invoker.elements(param)))(
src => Task.delay(src.close)) { src =>
Task.delay { if (src.hasNext) src.next else throw End }
}
def dbWookie {
// grandparent_id, (grandparent_id, parent_id, child_id)
val invoker = Q.query[Int, (Int, Int, Int)](sql)
val es = elementsR(invoker, 42)
// ?, ?, ?
// nested emits (42, ((35, (1, 3, 7)), (36, (8, 9, 12))))
}
I don't see too many functions like foldLeft and scanLeft on Process so I am not sure how to detect when grandparent_id, parent_id or child_id changes and emit a group. Any ideas?