Procesando funcionalmente un cursor de base de datos en Scala
Cuando necesito leer millones de filas de la base de datos de una base de datos PostgreSQL usando el controlador JDBC, siempre uso un cursor, de lo contrario obtendré un OutOfMemoryError. Aquí está el patrón (pseudocódigo) que uso:
begin transaction
execute("declare cursor...")
while (true) {
boolean processedSomeRows = false
resultSet = executeQuery("fetch forward...")
while (resultSet.next()) {
processedSomeRows = true
...
}
if (!processedSomeRows) break
}
close cursor
commit
Este es un equivalente más "funcional" que se me ocurrió implementar en Scala:
begin transaction
execute("declare cursor...")
@tailrec
def loop(resultSet: ResultSet,
processed: Boolean): Boolean = {
if (!resultSet.next()) processed
else {
// Process current result set row
loop(resultSet, true)
}
}
while (loop(executeQuery("fetch forward..."), false))
; //Empty loop
close cursor
commit
Sé que esto es artificial, pero ¿hay una mejor manera sin recurrir a la mutabilidad? Si estuviera tratando de hacer esto en Haskell, podría encontrar una solución que involucre mónadas, pero no quiero enviar mi mente a esos "pequeños pasajes retorcidos, todos por igual", porque nunca regresará ...