patternMinor
Realizing a SQL ResultSet into a Map in Scala
Viewed 0 times
maprealizingintosqlscalaresultset
Problem
I am trying to realize a java.sql.ResultSet into a map, in Scala.
I feel this could (should) be less verbose. If while/yield comprehensions existed, or some
comprehension for create a map. The client code needs a java map for now, but if an elegant
enough solution can produce a Scala map, I could convert it.
import java.sql.{ResultSet, ResultSetMetaData}
class DbRow extends java.util.HashMap[java.lang.String, Object] {
}
object freeFunctions {
def realize(queryResult: ResultSet): Vector[DbRow] = {
val md = queryResult.getMetaData
val colNames = for (i <- 1 to md.getColumnCount) yield md.getColumnName(i)
var rows: Vector[DbRow] = Vector.empty
while (queryResult.next()) {
val row = new DbRow
for (n <- colNames) {
row.put(n, queryResult.getObject(n))
}
rows = rows :+ row
}
rows
}
}I feel this could (should) be less verbose. If while/yield comprehensions existed, or some
comprehension for create a map. The client code needs a java map for now, but if an elegant
enough solution can produce a Scala map, I could convert it.
Solution
I don't have the time to test this, so I hope you can do that for me. I decided not to use HashMap straight away because type conversion makes things a bit more complicated than they should, but let me know if this is important for you and causes you trouble.
Here's option 1:
I don't like it much because some parts of the code rely on side effects of other parts of the code, so even if it works, it's still ugly.
Here's option 2, which I like more:
Nicer, IMHO, you can save some dots over there but I decided to keep them. Maybe something like this:
Again, I didn't test it, I don't know how to do it without a DB and I don't feel like setting one up now, sorry for that.
Finally, I'm not sure if you realized this, but "realize" is probably not the best name for this method (or for any method, unless you are programming some epistemic system, IMHO).
Here's option 1:
def realize(queryResult: ResultSet): Vector[Map[String, Object]] = {
val md = queryResult.getMetaData
val colNames = for (i (for (n queryResult.getObject(n)).toMap
Iterator.continually(queryResult.next()).takeWhile(identity).map(_ => buildMap()).toVector
}I don't like it much because some parts of the code rely on side effects of other parts of the code, so even if it works, it's still ugly.
Here's option 2, which I like more:
def buildMap(queryResult: ResultSet, colNames: Seq[String]): Option[Map[String, Object]] =
if (queryResult.next())
Some(colNames.map(n => n -> queryResult.getObject(n)).toMap)
else
None
def realize(queryResult: ResultSet): Vector[Map[String, Object]] = {
val md = queryResult.getMetaData
val colNames = (1 to md.getColumnCount) map md.getColumnName
Iterator.continually(buildMap(queryResult, colNames)).takeWhile(!_.isEmpty).map(_.get).toVector
}Nicer, IMHO, you can save some dots over there but I decided to keep them. Maybe something like this:
(Iterator continually (buildMap(queryResult, colNames)) takeWhile (!_.isEmpty) map (_.get)).toVectorAgain, I didn't test it, I don't know how to do it without a DB and I don't feel like setting one up now, sorry for that.
Finally, I'm not sure if you realized this, but "realize" is probably not the best name for this method (or for any method, unless you are programming some epistemic system, IMHO).
Code Snippets
def realize(queryResult: ResultSet): Vector[Map[String, Object]] = {
val md = queryResult.getMetaData
val colNames = for (i <- 1 to md.getColumnCount) yield md.getColumnName(i)
val buildMap = () => (for (n <- colNames) yield n -> queryResult.getObject(n)).toMap
Iterator.continually(queryResult.next()).takeWhile(identity).map(_ => buildMap()).toVector
}def buildMap(queryResult: ResultSet, colNames: Seq[String]): Option[Map[String, Object]] =
if (queryResult.next())
Some(colNames.map(n => n -> queryResult.getObject(n)).toMap)
else
None
def realize(queryResult: ResultSet): Vector[Map[String, Object]] = {
val md = queryResult.getMetaData
val colNames = (1 to md.getColumnCount) map md.getColumnName
Iterator.continually(buildMap(queryResult, colNames)).takeWhile(!_.isEmpty).map(_.get).toVector
}(Iterator continually (buildMap(queryResult, colNames)) takeWhile (!_.isEmpty) map (_.get)).toVectorContext
StackExchange Code Review Q#64662, answer score: 5
Revisions (0)
No revisions yet.