From 93f4700613dfa686155b3fafdff2a283eb812bb8 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 22 Feb 2025 21:04:10 -0500 Subject: [PATCH] WIP on integration tests --- .idea/modules.xml | 8 ++ documents.iml | 8 ++ src/integration-test/kotlin/CustomSQLiteIT.kt | 43 +++++++ src/main/kotlin/ConnectionExtensions.kt | 33 ++++-- src/main/kotlin/Custom.kt | 110 ++++++++++++++++++ 5 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 .idea/modules.xml create mode 100644 documents.iml create mode 100644 src/integration-test/kotlin/CustomSQLiteIT.kt create mode 100644 src/main/kotlin/Custom.kt diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..724dd10 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/documents.iml b/documents.iml new file mode 100644 index 0000000..ce12650 --- /dev/null +++ b/documents.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/integration-test/kotlin/CustomSQLiteIT.kt b/src/integration-test/kotlin/CustomSQLiteIT.kt new file mode 100644 index 0000000..c15ff76 --- /dev/null +++ b/src/integration-test/kotlin/CustomSQLiteIT.kt @@ -0,0 +1,43 @@ +package solutions.bitbadger.documents + +import kotlinx.serialization.Serializable +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import solutions.bitbadger.documents.query.Definition +import solutions.bitbadger.documents.query.Find +import kotlin.test.assertEquals + + +class CustomSQLiteIT { + + private val tbl = "test_table"; + + @BeforeEach + fun setUp() { + Configuration.connectionString = "jdbc:sqlite:memory" + } + + /** + * Reset the dialect + */ + @AfterEach + fun cleanUp() { + Configuration.dialectValue = null + } + + @Test + @DisplayName("list succeeds with empty list") + fun listEmpty() { + Configuration.dbConn().use { conn -> + conn.customNonQuery(Definition.ensureTable(tbl), listOf()) + conn.customNonQuery(Definition.ensureKey(tbl, Dialect.SQLITE), listOf()) + val result = conn.customList(Find.all(tbl), listOf(), Results::fromData) + assertEquals(0, result.size, "There should have been no results") + } + } +} + +@Serializable +data class TestDocument(val id: String) diff --git a/src/main/kotlin/ConnectionExtensions.kt b/src/main/kotlin/ConnectionExtensions.kt index 51f7f93..553107b 100644 --- a/src/main/kotlin/ConnectionExtensions.kt +++ b/src/main/kotlin/ConnectionExtensions.kt @@ -11,11 +11,9 @@ import java.sql.ResultSet * @param mapFunc The mapping function between the document and the domain item * @return A list of results for the given query */ -inline fun Connection.customList(query: String, parameters: Collection>, - mapFunc: (ResultSet) -> TDoc): List = - Parameters.apply(this, query, parameters).use { stmt -> - Results.toCustomList(stmt, mapFunc) - } +inline fun Connection.customList( + query: String, parameters: Collection>, mapFunc: (ResultSet) -> TDoc +) = Custom.list(query, parameters, this, mapFunc) /** * Execute a query that returns one or no results @@ -25,9 +23,9 @@ inline fun Connection.customList(query: String, parameters: Colle * @param mapFunc The mapping function between the document and the domain item * @return The document if one matches the query, `null` otherwise */ -inline fun Connection.customSingle(query: String, parameters: Collection>, - mapFunc: (ResultSet) -> TDoc): TDoc? = - this.customList("$query LIMIT 1", parameters, mapFunc).singleOrNull() +inline fun Connection.customSingle( + query: String, parameters: Collection>, mapFunc: (ResultSet) -> TDoc +) = Custom.single(query, parameters, this, mapFunc) /** * Execute a query that returns no results @@ -35,6 +33,19 @@ inline fun Connection.customSingle(query: String, parameters: Col * @param query The query to retrieve the results * @param parameters Parameters to use for the query */ -fun Connection.customNonQuery(query: String, parameters: Collection>) { - Parameters.apply(this, query, parameters).use { it.executeUpdate() } -} +fun Connection.customNonQuery(query: String, parameters: Collection>) = + Custom.nonQuery(query, parameters, this) + +/** + * Execute a query that returns a scalar result + * + * @param query The query to retrieve the result + * @param parameters Parameters to use for the query + * @param mapFunc The mapping function between the document and the domain item + * @return The scalar value from the query + */ +inline fun Connection.customScalar( + query: String, + parameters: Collection>, + mapFunc: (ResultSet) -> T & Any +) = Custom.scalar(query, parameters, this, mapFunc) diff --git a/src/main/kotlin/Custom.kt b/src/main/kotlin/Custom.kt new file mode 100644 index 0000000..87aa352 --- /dev/null +++ b/src/main/kotlin/Custom.kt @@ -0,0 +1,110 @@ +package solutions.bitbadger.documents + +import java.sql.Connection +import java.sql.ResultSet + +/** + * Custom query execution functions + */ +object Custom { + + /** + * Execute a query that returns a list of results + * + * @param query The query to retrieve the results + * @param parameters Parameters to use for the query + * @param conn The connection over which the query should be executed + * @param mapFunc The mapping function between the document and the domain item + * @return A list of results for the given query + */ + inline fun list( + query: String, parameters: Collection>, conn: Connection, mapFunc: (ResultSet) -> TDoc + ) = Parameters.apply(conn, query, parameters).use { Results.toCustomList(it, mapFunc) } + + /** + * Execute a query that returns a list of results (creates connection) + * + * @param query The query to retrieve the results + * @param parameters Parameters to use for the query + * @param mapFunc The mapping function between the document and the domain item + * @return A list of results for the given query + */ + inline fun list( + query: String, parameters: Collection>, mapFunc: (ResultSet) -> TDoc + ) = Configuration.dbConn().use { list(query, parameters, it, mapFunc) } + + /** + * Execute a query that returns one or no results + * + * @param query The query to retrieve the results + * @param parameters Parameters to use for the query + * @param conn The connection over which the query should be executed + * @param mapFunc The mapping function between the document and the domain item + * @return The document if one matches the query, `null` otherwise + */ + inline fun single( + query: String, parameters: Collection>, conn: Connection, mapFunc: (ResultSet) -> TDoc + ) = list("$query LIMIT 1", parameters, conn, mapFunc).singleOrNull() + + /** + * Execute a query that returns one or no results + * + * @param query The query to retrieve the results + * @param parameters Parameters to use for the query + * @param mapFunc The mapping function between the document and the domain item + * @return The document if one matches the query, `null` otherwise + */ + inline fun single( + query: String, parameters: Collection>, mapFunc: (ResultSet) -> TDoc + ) = Configuration.dbConn().use { single(query, parameters, it, mapFunc) } + + /** + * Execute a query that returns no results + * + * @param query The query to retrieve the results + * @param conn The connection over which the query should be executed + * @param parameters Parameters to use for the query + */ + fun nonQuery(query: String, parameters: Collection>, conn: Connection) { + Parameters.apply(conn, query, parameters).use { it.executeUpdate() } + } + + /** + * Execute a query that returns no results + * + * @param query The query to retrieve the results + * @param parameters Parameters to use for the query + */ + fun nonQuery(query: String, parameters: Collection>) = + Configuration.dbConn().use { nonQuery(query, parameters, it) } + + /** + * Execute a query that returns a scalar result + * + * @param query The query to retrieve the result + * @param parameters Parameters to use for the query + * @param conn The connection over which the query should be executed + * @param mapFunc The mapping function between the document and the domain item + * @return The scalar value from the query + */ + inline fun scalar( + query: String, parameters: Collection>, conn: Connection, mapFunc: (ResultSet) -> T & Any + ) = Parameters.apply(conn, query, parameters).use { stmt -> + stmt.executeQuery().use { rs -> + rs.next() + mapFunc(rs) + } + } + + /** + * Execute a query that returns a scalar result + * + * @param query The query to retrieve the result + * @param parameters Parameters to use for the query + * @param mapFunc The mapping function between the document and the domain item + * @return The scalar value from the query + */ + inline fun scalar( + query: String, parameters: Collection>, mapFunc: (ResultSet) -> T & Any + ) = Configuration.dbConn().use { scalar(query, parameters, it, mapFunc) } +}