Add JSON writer to Scala Custom

This commit is contained in:
Daniel J. Summers 2025-03-31 23:04:51 -04:00
parent 18866b3ff7
commit 40f8bded81
6 changed files with 172 additions and 10 deletions

View File

@ -2,6 +2,7 @@ package solutions.bitbadger.documents.scala
import solutions.bitbadger.documents.{Configuration, Parameter}
import java.io.PrintWriter
import java.sql.{Connection, ResultSet}
import scala.reflect.ClassTag
import scala.util.Using
@ -107,6 +108,60 @@ object Custom:
def jsonArray(query: String, mapFunc: ResultSet => String): String =
jsonArray(query, Nil, mapFunc)
/**
* Execute a query that writes a JSON array of results to the given `PrintWriter`
*
* @param query The query to retrieve the results
* @param parameters Parameters to use for the query
* @param writer The writer to which the results should be written
* @param conn The connection over which the query should be executed
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeJsonArray(query: String, parameters: Seq[Parameter[?]], writer: PrintWriter, conn: Connection,
mapFunc: ResultSet => String): Unit =
Using(Parameters.apply(conn, query, parameters)) { stmt => Results.writeJsonArray(writer, stmt, mapFunc) }
/**
* Execute a query that returns a JSON array of results
*
* @param query The query to retrieve the results
* @param writer The writer to which the results should be written
* @param conn The connection over which the query should be executed
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeJsonArray(query: String, conn: Connection, writer: PrintWriter, mapFunc: ResultSet => String): Unit =
writeJsonArray(query, Nil, writer, conn, mapFunc)
/**
* Execute a query that returns a JSON array of results (creates connection)
*
* @param query The query to retrieve the results
* @param parameters Parameters to use for the query
* @param writer The writer to which the results should be written
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeJsonArray(query: String, parameters: Seq[Parameter[?]], writer: PrintWriter,
mapFunc: ResultSet => String): Unit =
Using(Configuration.dbConn()) { conn => writeJsonArray(query, parameters, writer, conn, mapFunc) }
/**
* Execute a query that returns a JSON array of results (creates connection)
*
* @param query The query to retrieve the results
* @param writer The writer to which the results should be written
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeJsonArray(query: String, writer: PrintWriter, mapFunc: ResultSet => String): Unit =
writeJsonArray(query, Nil, writer, mapFunc)
/**
* Execute a query that returns one or no results
*

View File

@ -3,6 +3,7 @@ package solutions.bitbadger.documents.scala
import solutions.bitbadger.documents.DocumentException
import solutions.bitbadger.documents.java.Results as CoreResults
import java.io.PrintWriter
import java.sql.{PreparedStatement, ResultSet, SQLException}
import scala.collection.mutable.ListBuffer
import scala.reflect.ClassTag
@ -47,9 +48,8 @@ object Results:
try
val buffer = ListBuffer[Doc]()
Using(stmt.executeQuery()) { rs =>
while (rs.next()) {
while rs.next() do
buffer.append(mapFunc(rs, tag))
}
}
buffer.toList
catch
@ -107,12 +107,37 @@ object Results:
try
val results = StringBuilder("[")
Using(stmt.executeQuery()) { rs =>
while (rs.next()) {
while rs.next() do
if (results.length > 2) results.append(",")
results.append(mapFunc(rs))
}
}
results.append("]").toString()
catch
case ex: SQLException =>
throw DocumentException("Error retrieving documents from query: ${ex.message}", ex)
case ex: SQLException => throw DocumentException("Error retrieving documents from query: ${ex.message}", ex)
/**
* Write a JSON array of items for the results of the given command to the given `PrintWriter`, using the specified
* mapping function
*
* @param writer The writer for the results of the query
* @param stmt The prepared statement to execute
* @param mapFunc The mapping function from data reader to JSON text
* @return A string with a JSON array of documents from the query's result
* @throws DocumentException If there is a problem executing the query (unchecked)
*/
def writeJsonArray(writer: PrintWriter, stmt: PreparedStatement, mapFunc: ResultSet => String): Unit =
try
writer.write("[")
Using(stmt.executeQuery()) { rs =>
var isFirst = true
while rs.next() do
if isFirst then
isFirst = false
else
writer.write(",")
writer.write(mapFunc(rs))
}
writer.write("]")
catch
case ex: SQLException => throw DocumentException("Error writing documents from query: ${ex.message}", ex)

View File

@ -3,6 +3,7 @@ package solutions.bitbadger.documents.scala.extensions
import solutions.bitbadger.documents.{DocumentIndex, Field, FieldMatch, Parameter}
import solutions.bitbadger.documents.scala.*
import java.io.PrintWriter
import java.sql.{Connection, ResultSet}
import scala.reflect.ClassTag
@ -58,6 +59,32 @@ extension (conn: Connection)
def customJsonArray(query: String, mapFunc: ResultSet => String): String =
Custom.jsonArray(query, mapFunc)
/**
* Execute a query that writes a JSON array of results to the given `PrintWriter`
*
* @param query The query to retrieve the results
* @param parameters Parameters to use for the query
* @param writer The writer to which the results should be written
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeCustomJsonArray(query: String, parameters: Seq[Parameter[?]], writer: PrintWriter,
mapFunc: ResultSet => String): Unit =
Custom.writeJsonArray(query, parameters, writer, conn, mapFunc)
/**
* Execute a query that writes a JSON array of results to the given `PrintWriter`
*
* @param query The query to retrieve the results
* @param writer The writer to which the results should be written
* @param mapFunc The mapping function to extract the JSON from the query
* @return A JSON array of results for the given query
* @throws DocumentException If parameters are invalid
*/
def writeCustomJsonArray(query: String, writer: PrintWriter, mapFunc: ResultSet => String): Unit =
Custom.writeJsonArray(query, writer, mapFunc)
/**
* Execute a query that returns one or no results
*

View File

@ -7,6 +7,7 @@ import solutions.bitbadger.documents.scala.extensions.*
import solutions.bitbadger.documents.scala.tests.TEST_TABLE
import solutions.bitbadger.documents.{Configuration, Field, Parameter, ParameterType}
import java.io.{PrintWriter, StringWriter}
import scala.jdk.CollectionConverters.*
object CustomFunctions:
@ -29,19 +30,43 @@ object CustomFunctions:
def jsonArraySingle(db: ThrowawayDatabase): Unit =
db.conn.insert(TEST_TABLE, ArrayDocument("one", "2" :: "3" :: Nil))
assertEquals(JsonFunctions.maybeJsonB("[{\"id\":\"one\",\"values\":[\"2\",\"3\"]}]"),
assertEquals(JsonFunctions.maybeJsonB("""[{"id":"one","values":["2","3"]}]"""),
db.conn.customJsonArray(FindQuery.all(TEST_TABLE), Nil, Results.jsonFromData),
"A single document list was not represented correctly")
def jsonArrayMany(db: ThrowawayDatabase): Unit =
ArrayDocument.testDocuments.foreach { doc => db.conn.insert(TEST_TABLE, doc) }
assertEquals(JsonFunctions.maybeJsonB("[{\"id\":\"first\",\"values\":[\"a\",\"b\",\"c\"]},"
+ "{\"id\":\"second\",\"values\":[\"c\",\"d\",\"e\"]},"
+ "{\"id\":\"third\",\"values\":[\"x\",\"y\",\"z\"]}]"),
assertEquals(JsonFunctions.maybeJsonB("""[{"id":"first","values":["a","b","c"]},"""
+ """{"id":"second","values":["c","d","e"]},{"id":"third","values":["x","y","z"]}]"""),
db.conn.customJsonArray(FindQuery.all(TEST_TABLE) + QueryUtils.orderBy((Field.named("id") :: Nil).asJava), Nil,
Results.jsonFromData),
"A multiple document list was not represented correctly")
def writeJsonArrayEmpty(db: ThrowawayDatabase): Unit =
assertEquals(0L, db.conn.countAll(TEST_TABLE), "The test table should be empty")
val output = StringWriter()
val writer = PrintWriter(output)
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE), Nil, writer, Results.jsonFromData)
assertEquals("[]", output.toString, "An empty list was not represented correctly")
def writeJsonArraySingle(db: ThrowawayDatabase): Unit =
db.conn.insert(TEST_TABLE, ArrayDocument("one", "2" :: "3" :: Nil))
val output = StringWriter()
val writer = PrintWriter(output)
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE), Nil, writer, Results.jsonFromData)
assertEquals(JsonFunctions.maybeJsonB("""[{"id":"one","values":["2","3"]}]"""), output.toString,
"A single document list was not represented correctly")
def writeJsonArrayMany(db: ThrowawayDatabase): Unit =
ArrayDocument.testDocuments.foreach { doc => db.conn.insert(TEST_TABLE, doc) }
val output = StringWriter()
val writer = PrintWriter(output)
db.conn.writeCustomJsonArray(FindQuery.all(TEST_TABLE) + QueryUtils.orderBy((Field.named("id") :: Nil).asJava), Nil,
writer, Results.jsonFromData)
assertEquals(JsonFunctions.maybeJsonB("""[{"id":"first","values":["a","b","c"]},"""
+ """{"id":"second","values":["c","d","e"]},{"id":"third","values":["x","y","z"]}]"""),
output.toString, "A multiple document list was not represented correctly")
def singleNone(db: ThrowawayDatabase): Unit =
assertTrue(db.conn.customSingle[JsonDocument](FindQuery.all(TEST_TABLE), Results.fromData).isEmpty,
"There should not have been a document returned")

View File

@ -32,6 +32,21 @@ class PostgreSQLCustomIT:
def jsonArrayMany(): Unit =
Using(PgDB()) { db => CustomFunctions.jsonArrayMany(db) }
@Test
@DisplayName("writeJsonArray succeeds with empty array")
def writeJsonArrayEmpty(): Unit =
Using(PgDB()) { db => CustomFunctions.writeJsonArrayEmpty(db) }
@Test
@DisplayName("writeJsonArray succeeds with a single-item array")
def writeJsonArraySingle(): Unit =
Using(PgDB()) { db => CustomFunctions.writeJsonArraySingle(db) }
@Test
@DisplayName("writeJsonArray succeeds with a multi-item array")
def writeJsonArrayMany(): Unit =
Using(PgDB()) { db => CustomFunctions.writeJsonArrayMany(db) }
@Test
@DisplayName("single succeeds when document not found")
def singleNone(): Unit =

View File

@ -32,6 +32,21 @@ class SQLiteCustomIT:
def jsonArrayMany(): Unit =
Using(SQLiteDB()) { db => CustomFunctions.jsonArrayMany(db) }
@Test
@DisplayName("writeJsonArray succeeds with empty array")
def writeJsonArrayEmpty(): Unit =
Using(SQLiteDB()) { db => CustomFunctions.writeJsonArrayEmpty(db) }
@Test
@DisplayName("writeJsonArray succeeds with a single-item array")
def writeJsonArraySingle(): Unit =
Using(SQLiteDB()) { db => CustomFunctions.writeJsonArraySingle(db) }
@Test
@DisplayName("writeJsonArray succeeds with a multi-item array")
def writeJsonArrayMany(): Unit =
Using(SQLiteDB()) { db => CustomFunctions.writeJsonArrayMany(db) }
@Test
@DisplayName("single succeeds when document not found")
def singleNone(): Unit =