From 2eedb1cf1c02c7bb43518bc45b3400f9adf1cd8b Mon Sep 17 00:00:00 2001 From: Brian Campbell Date: Tue, 8 May 2018 08:55:01 -0600 Subject: [PATCH] Provide a streaming result set Allow users who want access to an underlying result set that is large to do so through use of streamed statements --- .../scala/com/lucidchart/relate/SqlQuery.scala | 16 ++++++++++++++++ relate/src/test/scala/RelateITSpec.scala | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/relate/src/main/scala/com/lucidchart/relate/SqlQuery.scala b/relate/src/main/scala/com/lucidchart/relate/SqlQuery.scala index 3dd2c45..d3f936f 100644 --- a/relate/src/main/scala/com/lucidchart/relate/SqlQuery.scala +++ b/relate/src/main/scala/com/lucidchart/relate/SqlQuery.scala @@ -79,6 +79,22 @@ trait Sql { */ def results()(implicit connection: Connection): ResultSet = normalStatement.results() + /** + * Provides a java.sql.ResultSet that streams records from the database. + * This allows for interacting with large data sets with less risk of OutOfMemoryErrors. + * Many JDBC connectors will not allow for additional queries to the connection until the + * returned ResultSet has been closed. + * @param fetchSize the number of rows to fetch at a time, defaults to 100. If the JDBC Driver + * is MySQL, the fetchSize will always default to Int.MinValue, as MySQL's JDBC implementation + * ignores all other fetchSize values and only streams if fetchSize is Int.MinValue + * @param connection the db connection to use when executing the query + * @return java.sql.ResultSet that streams data from the database + */ + def streamingResults(fetchSize: Int)(implicit connection: Connection): ResultSet = { + val prepared = streamedStatement(fetchSize) + prepared.results() + } + /** * Execute a statement * @param connection the db connection to use when executing the query diff --git a/relate/src/test/scala/RelateITSpec.scala b/relate/src/test/scala/RelateITSpec.scala index 8164531..bf8c529 100644 --- a/relate/src/test/scala/RelateITSpec.scala +++ b/relate/src/test/scala/RelateITSpec.scala @@ -465,6 +465,23 @@ class RelateITSpec extends Specification with Db { } } + "results" should { + val ids = Array(1L, 2L, 3L) + "work from ResultSet" in withConnection { implicit connection => + val resultSet = sql"SELECT * FROM pokedex WHERE id in ($ids)".results() + val pokemonNames = SqlResult(resultSet).asList(pokedexParser).map(_.name) + + (pokemonNames must contain("Squirtle")) and (pokemonNames must contain("Wartortle")) and (pokemonNames must contain("Blastoise")) + } + + "work from streaming ResultSet" in withConnection { implicit connection => + val resultSet = sql"SELECT * FROM pokedex WHERE id in ($ids)".streamingResults(1) + val pokemonNames = SqlResult(resultSet).asList(pokedexParser).map(_.name) + + (pokemonNames must contain("Squirtle")) and (pokemonNames must contain("Wartortle")) and (pokemonNames must contain("Blastoise")) + } + } + "update" should { "update matched rows and not update unmatched rows" in withConnection { implicit connection => val correct = List(